blob: 1403bd19d61c51b6aecea7776d69e3170e4ce2af [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
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200324/* Report a warning if a rule is placed after a 'tcp-request content' rule.
325 * Return 1 if the warning has been emitted, otherwise 0.
326 */
327int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
328{
329 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
330 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
331 file, line, arg);
332 return 1;
333 }
334 return 0;
335}
336
Willy Tarreau61d18892009-03-31 10:49:21 +0200337/* Report a warning if a rule is placed after a 'block' rule.
338 * Return 1 if the warning has been emitted, otherwise 0.
339 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100340int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200341{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200342 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200343 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
344 file, line, arg);
345 return 1;
346 }
347 return 0;
348}
349
Willy Tarreau5002f572014-04-23 01:32:02 +0200350/* Report a warning if a rule is placed after an 'http_request' rule.
351 * Return 1 if the warning has been emitted, otherwise 0.
352 */
353int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
354{
355 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
356 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
357 file, line, arg);
358 return 1;
359 }
360 return 0;
361}
362
Willy Tarreau61d18892009-03-31 10:49:21 +0200363/* Report a warning if a rule is placed after a reqrewrite rule.
364 * Return 1 if the warning has been emitted, otherwise 0.
365 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100366int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200367{
368 if (proxy->req_exp) {
369 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
370 file, line, arg);
371 return 1;
372 }
373 return 0;
374}
375
376/* Report a warning if a rule is placed after a reqadd rule.
377 * Return 1 if the warning has been emitted, otherwise 0.
378 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100379int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200380{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100381 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200382 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
383 file, line, arg);
384 return 1;
385 }
386 return 0;
387}
388
389/* Report a warning if a rule is placed after a redirect rule.
390 * Return 1 if the warning has been emitted, otherwise 0.
391 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100392int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200393{
394 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
395 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
396 file, line, arg);
397 return 1;
398 }
399 return 0;
400}
401
402/* Report a warning if a rule is placed after a 'use_backend' rule.
403 * Return 1 if the warning has been emitted, otherwise 0.
404 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100405int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200406{
407 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
408 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
409 file, line, arg);
410 return 1;
411 }
412 return 0;
413}
414
Willy Tarreauee445d92014-04-23 01:39:04 +0200415/* Report a warning if a rule is placed after a 'use-server' rule.
416 * Return 1 if the warning has been emitted, otherwise 0.
417 */
418int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
419{
420 if (!LIST_ISEMPTY(&proxy->server_rules)) {
421 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
422 file, line, arg);
423 return 1;
424 }
425 return 0;
426}
427
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200428/* report a warning if a "tcp request connection" rule is dangerously placed */
429int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
430{
431 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
432 warnif_rule_after_block(proxy, file, line, arg) ||
433 warnif_rule_after_http_req(proxy, file, line, arg) ||
434 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
435 warnif_rule_after_reqadd(proxy, file, line, arg) ||
436 warnif_rule_after_redirect(proxy, file, line, arg) ||
437 warnif_rule_after_use_backend(proxy, file, line, arg) ||
438 warnif_rule_after_use_server(proxy, file, line, arg);
439}
440
441/* report a warning if a "tcp request content" rule is dangerously placed */
442int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
443{
444 return warnif_rule_after_block(proxy, file, line, arg) ||
445 warnif_rule_after_http_req(proxy, file, line, arg) ||
446 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
447 warnif_rule_after_reqadd(proxy, file, line, arg) ||
448 warnif_rule_after_redirect(proxy, file, line, arg) ||
449 warnif_rule_after_use_backend(proxy, file, line, arg) ||
450 warnif_rule_after_use_server(proxy, file, line, arg);
451}
452
Willy Tarreau61d18892009-03-31 10:49:21 +0200453/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100454int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200455{
Willy Tarreau5002f572014-04-23 01:32:02 +0200456 return warnif_rule_after_http_req(proxy, file, line, arg) ||
457 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
458 warnif_rule_after_reqadd(proxy, file, line, arg) ||
459 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200460 warnif_rule_after_use_backend(proxy, file, line, arg) ||
461 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200462}
463
464/* report a warning if an http-request rule is dangerously placed */
465int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
466{
Willy Tarreau61d18892009-03-31 10:49:21 +0200467 return 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) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200470 warnif_rule_after_use_backend(proxy, file, line, arg) ||
471 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200472}
473
474/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100475int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200476{
477 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
478 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200479 warnif_rule_after_use_backend(proxy, file, line, arg) ||
480 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200481}
482
483/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100484int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200485{
486 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200487 warnif_rule_after_use_backend(proxy, file, line, arg) ||
488 warnif_rule_after_use_server(proxy, file, line, arg);
489}
490
491/* report a warning if a redirect rule is dangerously placed */
492int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
493{
494 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
495 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200496}
497
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100498/* Report it if a request ACL condition uses some keywords that are incompatible
499 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
500 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
501 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100502 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100503static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100504{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100505 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200506 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100507
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100508 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100509 return 0;
510
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100511 acl = acl_cond_conflicts(cond, where);
512 if (acl) {
513 if (acl->name && *acl->name)
514 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
515 file, line, acl->name, sample_ckp_names(where));
516 else
517 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 +0200518 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100519 return ERR_WARN;
520 }
521 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100522 return 0;
523
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100524 if (acl->name && *acl->name)
525 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200526 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100527 else
528 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200529 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100530 return ERR_WARN;
531}
532
Willy Tarreaubaaee002006-06-26 02:48:02 +0200533/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200534 * parse a line in a <global> section. Returns the error code, 0 if OK, or
535 * any combination of :
536 * - ERR_ABORT: must abort ASAP
537 * - ERR_FATAL: we can continue parsing but not start the service
538 * - ERR_WARN: a warning has been emitted
539 * - ERR_ALERT: an alert has been emitted
540 * Only the two first ones can stop processing, the two others are just
541 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200542 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200543int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200544{
Willy Tarreau058e9072009-07-20 09:30:05 +0200545 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200546 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200547
548 if (!strcmp(args[0], "global")) { /* new section */
549 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200551 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200552 else if (!strcmp(args[0], "ca-base")) {
553#ifdef USE_OPENSSL
554 if (global.ca_base != NULL) {
555 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
556 err_code |= ERR_ALERT;
557 goto out;
558 }
559 if (*(args[1]) == 0) {
560 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT | ERR_FATAL;
562 goto out;
563 }
564 global.ca_base = strdup(args[1]);
565#else
566 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
567 err_code |= ERR_ALERT | ERR_FATAL;
568 goto out;
569#endif
570 }
571 else if (!strcmp(args[0], "crt-base")) {
572#ifdef USE_OPENSSL
573 if (global.crt_base != NULL) {
574 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
575 err_code |= ERR_ALERT;
576 goto out;
577 }
578 if (*(args[1]) == 0) {
579 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
580 err_code |= ERR_ALERT | ERR_FATAL;
581 goto out;
582 }
583 global.crt_base = strdup(args[1]);
584#else
585 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
586 err_code |= ERR_ALERT | ERR_FATAL;
587 goto out;
588#endif
589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 else if (!strcmp(args[0], "daemon")) {
591 global.mode |= MODE_DAEMON;
592 }
593 else if (!strcmp(args[0], "debug")) {
594 global.mode |= MODE_DEBUG;
595 }
596 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100597 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200598 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200599 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100600 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200601 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100603 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200604 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100605 else if (!strcmp(args[0], "nosplice")) {
606 global.tune.options &= ~GTUNE_USE_SPLICE;
607 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200608 else if (!strcmp(args[0], "nogetaddrinfo")) {
609 global.tune.options &= ~GTUNE_USE_GAI;
610 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611 else if (!strcmp(args[0], "quiet")) {
612 global.mode |= MODE_QUIET;
613 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200614 else if (!strcmp(args[0], "tune.maxpollevents")) {
615 if (global.tune.maxpollevents != 0) {
616 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200617 err_code |= ERR_ALERT;
618 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200619 }
620 if (*(args[1]) == 0) {
621 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200622 err_code |= ERR_ALERT | ERR_FATAL;
623 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200624 }
625 global.tune.maxpollevents = atol(args[1]);
626 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100627 else if (!strcmp(args[0], "tune.maxaccept")) {
628 if (global.tune.maxaccept != 0) {
629 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200630 err_code |= ERR_ALERT;
631 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100632 }
633 if (*(args[1]) == 0) {
634 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200635 err_code |= ERR_ALERT | ERR_FATAL;
636 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100637 }
638 global.tune.maxaccept = atol(args[1]);
639 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200640 else if (!strcmp(args[0], "tune.chksize")) {
641 if (*(args[1]) == 0) {
642 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
643 err_code |= ERR_ALERT | ERR_FATAL;
644 goto out;
645 }
646 global.tune.chksize = atol(args[1]);
647 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200648#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200649 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
650 global.tune.sslprivatecache = 1;
651 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100652 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200653 if (*(args[1]) == 0) {
654 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
655 err_code |= ERR_ALERT | ERR_FATAL;
656 goto out;
657 }
658 global.tune.sslcachesize = atol(args[1]);
659 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100660 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
661 unsigned int ssllifetime;
662 const char *res;
663
664 if (*(args[1]) == 0) {
665 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
666 err_code |= ERR_ALERT | ERR_FATAL;
667 goto out;
668 }
669
670 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
671 if (res) {
672 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
673 file, linenum, *res, args[0]);
674 err_code |= ERR_ALERT | ERR_FATAL;
675 goto out;
676 }
677
678 global.tune.ssllifetime = ssllifetime;
679 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100680 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
681 if (*(args[1]) == 0) {
682 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
683 err_code |= ERR_ALERT | ERR_FATAL;
684 goto out;
685 }
686 global.tune.ssl_max_record = atol(args[1]);
687 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200688 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
689 if (*(args[1]) == 0) {
690 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
691 err_code |= ERR_ALERT | ERR_FATAL;
692 goto out;
693 }
694 global.tune.ssl_default_dh_param = atol(args[1]);
695 if (global.tune.ssl_default_dh_param < 1024) {
696 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
697 err_code |= ERR_ALERT | ERR_FATAL;
698 goto out;
699 }
700 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200701#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100702 else if (!strcmp(args[0], "tune.buffers.limit")) {
703 if (*(args[1]) == 0) {
704 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708 global.tune.buf_limit = atol(args[1]);
709 if (global.tune.buf_limit) {
710 if (global.tune.buf_limit < 3)
711 global.tune.buf_limit = 3;
712 if (global.tune.buf_limit <= global.tune.reserved_bufs)
713 global.tune.buf_limit = global.tune.reserved_bufs + 1;
714 }
715 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100716 else if (!strcmp(args[0], "tune.buffers.reserve")) {
717 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.reserved_bufs = atol(args[1]);
723 if (global.tune.reserved_bufs < 2)
724 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100725 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
726 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100727 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200728 else if (!strcmp(args[0], "tune.bufsize")) {
729 if (*(args[1]) == 0) {
730 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
731 err_code |= ERR_ALERT | ERR_FATAL;
732 goto out;
733 }
734 global.tune.bufsize = atol(args[1]);
735 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
736 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100737 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100738 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200739 }
740 else if (!strcmp(args[0], "tune.maxrewrite")) {
741 if (*(args[1]) == 0) {
742 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
743 err_code |= ERR_ALERT | ERR_FATAL;
744 goto out;
745 }
746 global.tune.maxrewrite = atol(args[1]);
747 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
748 global.tune.maxrewrite = global.tune.bufsize / 2;
749 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100750 else if (!strcmp(args[0], "tune.idletimer")) {
751 unsigned int idle;
752 const char *res;
753
754 if (*(args[1]) == 0) {
755 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
756 err_code |= ERR_ALERT | ERR_FATAL;
757 goto out;
758 }
759
760 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
761 if (res) {
762 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
763 file, linenum, *res, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
767
768 if (idle > 65535) {
769 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
772 }
773 global.tune.idle_timer = idle;
774 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100775 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
776 if (global.tune.client_rcvbuf != 0) {
777 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
778 err_code |= ERR_ALERT;
779 goto out;
780 }
781 if (*(args[1]) == 0) {
782 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
783 err_code |= ERR_ALERT | ERR_FATAL;
784 goto out;
785 }
786 global.tune.client_rcvbuf = atol(args[1]);
787 }
788 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
789 if (global.tune.server_rcvbuf != 0) {
790 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
791 err_code |= ERR_ALERT;
792 goto out;
793 }
794 if (*(args[1]) == 0) {
795 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
798 }
799 global.tune.server_rcvbuf = atol(args[1]);
800 }
801 else if (!strcmp(args[0], "tune.sndbuf.client")) {
802 if (global.tune.client_sndbuf != 0) {
803 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
804 err_code |= ERR_ALERT;
805 goto out;
806 }
807 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.client_sndbuf = atol(args[1]);
813 }
814 else if (!strcmp(args[0], "tune.sndbuf.server")) {
815 if (global.tune.server_sndbuf != 0) {
816 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
817 err_code |= ERR_ALERT;
818 goto out;
819 }
820 if (*(args[1]) == 0) {
821 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
822 err_code |= ERR_ALERT | ERR_FATAL;
823 goto out;
824 }
825 global.tune.server_sndbuf = atol(args[1]);
826 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200827 else if (!strcmp(args[0], "tune.pipesize")) {
828 if (*(args[1]) == 0) {
829 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
832 }
833 global.tune.pipesize = atol(args[1]);
834 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100835 else if (!strcmp(args[0], "tune.http.cookielen")) {
836 if (*(args[1]) == 0) {
837 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
838 err_code |= ERR_ALERT | ERR_FATAL;
839 goto out;
840 }
841 global.tune.cookie_len = atol(args[1]) + 1;
842 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200843 else if (!strcmp(args[0], "tune.http.maxhdr")) {
844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849 global.tune.max_http_hdr = atol(args[1]);
850 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100851 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
852#ifdef USE_ZLIB
853 if (*args[1]) {
854 global.tune.zlibmemlevel = atoi(args[1]);
855 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
856 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
857 file, linenum, args[0]);
858 err_code |= ERR_ALERT | ERR_FATAL;
859 goto out;
860 }
861 } else {
862 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
863 file, linenum, args[0]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867#else
868 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
869 err_code |= ERR_ALERT | ERR_FATAL;
870 goto out;
871#endif
872 }
873 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
874#ifdef USE_ZLIB
875 if (*args[1]) {
876 global.tune.zlibwindowsize = atoi(args[1]);
877 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
878 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
879 file, linenum, args[0]);
880 err_code |= ERR_ALERT | ERR_FATAL;
881 goto out;
882 }
883 } else {
884 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
885 file, linenum, args[0]);
886 err_code |= ERR_ALERT | ERR_FATAL;
887 goto out;
888 }
889#else
890 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
891 err_code |= ERR_ALERT | ERR_FATAL;
892 goto out;
893#endif
894 }
William Lallemandf3747832012-11-09 12:33:10 +0100895 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
896 if (*args[1]) {
897 global.tune.comp_maxlevel = atoi(args[1]);
898 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
899 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
900 file, linenum, args[0]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904 } else {
905 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
906 file, linenum, args[0]);
907 err_code |= ERR_ALERT | ERR_FATAL;
908 goto out;
909 }
910 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200911 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
912 if (*args[1]) {
913 global.tune.pattern_cache = atoi(args[1]);
914 if (global.tune.pattern_cache < 0) {
915 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
916 file, linenum, args[0]);
917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
919 }
920 } else {
921 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
922 file, linenum, args[0]);
923 err_code |= ERR_ALERT | ERR_FATAL;
924 goto out;
925 }
926 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 else if (!strcmp(args[0], "uid")) {
928 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200929 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200930 err_code |= ERR_ALERT;
931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 }
933 if (*(args[1]) == 0) {
934 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT | ERR_FATAL;
936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
938 global.uid = atol(args[1]);
939 }
940 else if (!strcmp(args[0], "gid")) {
941 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200942 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200943 err_code |= ERR_ALERT;
944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200945 }
946 if (*(args[1]) == 0) {
947 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200948 err_code |= ERR_ALERT | ERR_FATAL;
949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950 }
951 global.gid = atol(args[1]);
952 }
Simon Horman98637e52014-06-20 12:30:16 +0900953 else if (!strcmp(args[0], "external-check")) {
954 global.external_check = 1;
955 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200956 /* user/group name handling */
957 else if (!strcmp(args[0], "user")) {
958 struct passwd *ha_user;
959 if (global.uid != 0) {
960 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200961 err_code |= ERR_ALERT;
962 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200963 }
964 errno = 0;
965 ha_user = getpwnam(args[1]);
966 if (ha_user != NULL) {
967 global.uid = (int)ha_user->pw_uid;
968 }
969 else {
970 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 +0200971 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200972 }
973 }
974 else if (!strcmp(args[0], "group")) {
975 struct group *ha_group;
976 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200977 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200978 err_code |= ERR_ALERT;
979 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200980 }
981 errno = 0;
982 ha_group = getgrnam(args[1]);
983 if (ha_group != NULL) {
984 global.gid = (int)ha_group->gr_gid;
985 }
986 else {
987 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 +0200988 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200989 }
990 }
991 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200993 if (*(args[1]) == 0) {
994 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200995 err_code |= ERR_ALERT | ERR_FATAL;
996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997 }
998 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100999 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1000 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1001 file, linenum, args[0], LONGBITS, global.nbproc);
1002 err_code |= ERR_ALERT | ERR_FATAL;
1003 goto out;
1004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001005 }
1006 else if (!strcmp(args[0], "maxconn")) {
1007 if (global.maxconn != 0) {
1008 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001009 err_code |= ERR_ALERT;
1010 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001011 }
1012 if (*(args[1]) == 0) {
1013 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001014 err_code |= ERR_ALERT | ERR_FATAL;
1015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001016 }
1017 global.maxconn = atol(args[1]);
1018#ifdef SYSTEM_MAXCONN
1019 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1020 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);
1021 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001022 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001023 }
1024#endif /* SYSTEM_MAXCONN */
1025 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001026 else if (!strcmp(args[0], "maxsslconn")) {
1027#ifdef USE_OPENSSL
1028 if (*(args[1]) == 0) {
1029 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1030 err_code |= ERR_ALERT | ERR_FATAL;
1031 goto out;
1032 }
1033 global.maxsslconn = atol(args[1]);
1034#else
Emeric Brun0914df82012-10-02 18:45:42 +02001035 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1036 err_code |= ERR_ALERT | ERR_FATAL;
1037 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001038#endif
1039 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001040 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1041#ifdef USE_OPENSSL
1042 if (*(args[1]) == 0) {
1043 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1044 err_code |= ERR_ALERT | ERR_FATAL;
1045 goto out;
1046 }
1047 free(global.listen_default_ciphers);
1048 global.listen_default_ciphers = strdup(args[1]);
1049#else
1050 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1051 err_code |= ERR_ALERT | ERR_FATAL;
1052 goto out;
1053#endif
1054 }
1055 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1056#ifdef USE_OPENSSL
1057 if (*(args[1]) == 0) {
1058 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1059 err_code |= ERR_ALERT | ERR_FATAL;
1060 goto out;
1061 }
1062 free(global.connect_default_ciphers);
1063 global.connect_default_ciphers = strdup(args[1]);
1064#else
1065 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1066 err_code |= ERR_ALERT | ERR_FATAL;
1067 goto out;
1068#endif
1069 }
Emeric Brun850efd52014-01-29 12:24:34 +01001070 else if (!strcmp(args[0], "ssl-server-verify")) {
1071 if (*(args[1]) == 0) {
1072 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1073 err_code |= ERR_ALERT | ERR_FATAL;
1074 goto out;
1075 }
1076 if (strcmp(args[1],"none") == 0)
1077 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1078 else if (strcmp(args[1],"required") == 0)
1079 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1080 else {
1081 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1082 err_code |= ERR_ALERT | ERR_FATAL;
1083 goto out;
1084 }
1085 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001086 else if (!strcmp(args[0], "maxconnrate")) {
1087 if (global.cps_lim != 0) {
1088 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1089 err_code |= ERR_ALERT;
1090 goto out;
1091 }
1092 if (*(args[1]) == 0) {
1093 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1094 err_code |= ERR_ALERT | ERR_FATAL;
1095 goto out;
1096 }
1097 global.cps_lim = atol(args[1]);
1098 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001099 else if (!strcmp(args[0], "maxsessrate")) {
1100 if (global.sps_lim != 0) {
1101 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1102 err_code |= ERR_ALERT;
1103 goto out;
1104 }
1105 if (*(args[1]) == 0) {
1106 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1107 err_code |= ERR_ALERT | ERR_FATAL;
1108 goto out;
1109 }
1110 global.sps_lim = atol(args[1]);
1111 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001112 else if (!strcmp(args[0], "maxsslrate")) {
1113 if (global.ssl_lim != 0) {
1114 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1115 err_code |= ERR_ALERT;
1116 goto out;
1117 }
1118 if (*(args[1]) == 0) {
1119 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1120 err_code |= ERR_ALERT | ERR_FATAL;
1121 goto out;
1122 }
1123 global.ssl_lim = atol(args[1]);
1124 }
William Lallemandd85f9172012-11-09 17:05:39 +01001125 else if (!strcmp(args[0], "maxcomprate")) {
1126 if (*(args[1]) == 0) {
1127 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1128 err_code |= ERR_ALERT | ERR_FATAL;
1129 goto out;
1130 }
1131 global.comp_rate_lim = atoi(args[1]) * 1024;
1132 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001133 else if (!strcmp(args[0], "maxpipes")) {
1134 if (global.maxpipes != 0) {
1135 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT;
1137 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001138 }
1139 if (*(args[1]) == 0) {
1140 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001141 err_code |= ERR_ALERT | ERR_FATAL;
1142 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001143 }
1144 global.maxpipes = atol(args[1]);
1145 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001146 else if (!strcmp(args[0], "maxzlibmem")) {
1147 if (*(args[1]) == 0) {
1148 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1149 err_code |= ERR_ALERT | ERR_FATAL;
1150 goto out;
1151 }
William Lallemande3a7d992012-11-20 11:25:20 +01001152 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001153 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001154 else if (!strcmp(args[0], "maxcompcpuusage")) {
1155 if (*(args[1]) == 0) {
1156 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1157 err_code |= ERR_ALERT | ERR_FATAL;
1158 goto out;
1159 }
1160 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001161 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001162 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1163 err_code |= ERR_ALERT | ERR_FATAL;
1164 goto out;
1165 }
1166}
1167
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 else if (!strcmp(args[0], "ulimit-n")) {
1169 if (global.rlimit_nofile != 0) {
1170 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001171 err_code |= ERR_ALERT;
1172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173 }
1174 if (*(args[1]) == 0) {
1175 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001176 err_code |= ERR_ALERT | ERR_FATAL;
1177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001178 }
1179 global.rlimit_nofile = atol(args[1]);
1180 }
1181 else if (!strcmp(args[0], "chroot")) {
1182 if (global.chroot != NULL) {
1183 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001184 err_code |= ERR_ALERT;
1185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001186 }
1187 if (*(args[1]) == 0) {
1188 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001189 err_code |= ERR_ALERT | ERR_FATAL;
1190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001191 }
1192 global.chroot = strdup(args[1]);
1193 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001194 else if (!strcmp(args[0], "description")) {
1195 int i, len=0;
1196 char *d;
1197
1198 if (!*args[1]) {
1199 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1200 file, linenum, args[0]);
1201 err_code |= ERR_ALERT | ERR_FATAL;
1202 goto out;
1203 }
1204
Willy Tarreau348acfe2014-04-14 15:00:39 +02001205 for (i = 1; *args[i]; i++)
1206 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001207
1208 if (global.desc)
1209 free(global.desc);
1210
1211 global.desc = d = (char *)calloc(1, len);
1212
Willy Tarreau348acfe2014-04-14 15:00:39 +02001213 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1214 for (i = 2; *args[i]; i++)
1215 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001216 }
1217 else if (!strcmp(args[0], "node")) {
1218 int i;
1219 char c;
1220
1221 for (i=0; args[1][i]; i++) {
1222 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001223 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1224 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001225 break;
1226 }
1227
1228 if (!i || args[1][i]) {
1229 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1230 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1231 file, linenum, args[0]);
1232 err_code |= ERR_ALERT | ERR_FATAL;
1233 goto out;
1234 }
1235
1236 if (global.node)
1237 free(global.node);
1238
1239 global.node = strdup(args[1]);
1240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001241 else if (!strcmp(args[0], "pidfile")) {
1242 if (global.pidfile != NULL) {
1243 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001244 err_code |= ERR_ALERT;
1245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001246 }
1247 if (*(args[1]) == 0) {
1248 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001251 }
1252 global.pidfile = strdup(args[1]);
1253 }
Emeric Bruned760922010-10-22 17:59:25 +02001254 else if (!strcmp(args[0], "unix-bind")) {
1255 int cur_arg = 1;
1256 while (*(args[cur_arg])) {
1257 if (!strcmp(args[cur_arg], "prefix")) {
1258 if (global.unix_bind.prefix != NULL) {
1259 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1260 err_code |= ERR_ALERT;
1261 cur_arg += 2;
1262 continue;
1263 }
1264
1265 if (*(args[cur_arg+1]) == 0) {
1266 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1267 err_code |= ERR_ALERT | ERR_FATAL;
1268 goto out;
1269 }
1270 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1271 cur_arg += 2;
1272 continue;
1273 }
1274
1275 if (!strcmp(args[cur_arg], "mode")) {
1276
1277 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1278 cur_arg += 2;
1279 continue;
1280 }
1281
1282 if (!strcmp(args[cur_arg], "uid")) {
1283
1284 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1285 cur_arg += 2;
1286 continue;
1287 }
1288
1289 if (!strcmp(args[cur_arg], "gid")) {
1290
1291 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1292 cur_arg += 2;
1293 continue;
1294 }
1295
1296 if (!strcmp(args[cur_arg], "user")) {
1297 struct passwd *user;
1298
1299 user = getpwnam(args[cur_arg + 1]);
1300 if (!user) {
1301 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1302 file, linenum, args[0], args[cur_arg + 1 ]);
1303 err_code |= ERR_ALERT | ERR_FATAL;
1304 goto out;
1305 }
1306
1307 global.unix_bind.ux.uid = user->pw_uid;
1308 cur_arg += 2;
1309 continue;
1310 }
1311
1312 if (!strcmp(args[cur_arg], "group")) {
1313 struct group *group;
1314
1315 group = getgrnam(args[cur_arg + 1]);
1316 if (!group) {
1317 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1318 file, linenum, args[0], args[cur_arg + 1 ]);
1319 err_code |= ERR_ALERT | ERR_FATAL;
1320 goto out;
1321 }
1322
1323 global.unix_bind.ux.gid = group->gr_gid;
1324 cur_arg += 2;
1325 continue;
1326 }
1327
Willy Tarreaub48f9582011-09-05 01:17:06 +02001328 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001329 file, linenum, args[0]);
1330 err_code |= ERR_ALERT | ERR_FATAL;
1331 goto out;
1332 }
1333 }
William Lallemand0f99e342011-10-12 17:50:54 +02001334 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1335 /* delete previous herited or defined syslog servers */
1336 struct logsrv *back;
1337 struct logsrv *tmp;
1338
1339 if (*(args[1]) != 0) {
1340 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
1343 }
1344
1345 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1346 LIST_DEL(&tmp->list);
1347 free(tmp);
1348 }
1349 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001350 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001351 struct sockaddr_storage *sk;
1352 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001353 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001354 int arg = 0;
1355 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001356
Willy Tarreaubaaee002006-06-26 02:48:02 +02001357 if (*(args[1]) == 0 || *(args[2]) == 0) {
1358 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001359 err_code |= ERR_ALERT | ERR_FATAL;
1360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001361 }
William Lallemand0f99e342011-10-12 17:50:54 +02001362
1363 logsrv = calloc(1, sizeof(struct logsrv));
1364
Willy Tarreau18324f52014-06-27 18:10:07 +02001365 /* just after the address, a length may be specified */
1366 if (strcmp(args[arg+2], "len") == 0) {
1367 len = atoi(args[arg+3]);
1368 if (len < 80 || len > 65535) {
1369 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1370 file, linenum, args[arg+3]);
1371 err_code |= ERR_ALERT | ERR_FATAL;
1372 goto out;
1373 }
1374 logsrv->maxlen = len;
1375
1376 /* skip these two args */
1377 arg += 2;
1378 }
1379 else
1380 logsrv->maxlen = MAX_SYSLOG_LEN;
1381
1382 if (logsrv->maxlen > global.max_syslog_len) {
1383 global.max_syslog_len = logsrv->maxlen;
1384 logline = realloc(logline, global.max_syslog_len + 1);
1385 }
1386
1387 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001388 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001389 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001390 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001391 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392 }
1393
William Lallemand0f99e342011-10-12 17:50:54 +02001394 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001395 if (*(args[arg+3])) {
1396 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001397 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001398 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001399 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001400 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401 }
1402 }
1403
William Lallemand0f99e342011-10-12 17:50:54 +02001404 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001405 if (*(args[arg+4])) {
1406 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001407 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001408 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001409 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001410 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001411 }
1412 }
1413
Willy Tarreau902636f2013-03-10 19:44:48 +01001414 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001415 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001416 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001417 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001418 free(logsrv);
1419 goto out;
1420 }
1421 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001422
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001423 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001424 if (port1 != port2) {
1425 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1426 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001427 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001428 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001429 goto out;
1430 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001431
William Lallemand0f99e342011-10-12 17:50:54 +02001432 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001433 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001434 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001435 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001436
William Lallemand0f99e342011-10-12 17:50:54 +02001437 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001438 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001439 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1440 char *name;
1441 int len;
1442
1443 if (global.log_send_hostname != NULL) {
1444 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1445 err_code |= ERR_ALERT;
1446 goto out;
1447 }
1448
1449 if (*(args[1]))
1450 name = args[1];
1451 else
1452 name = hostname;
1453
1454 len = strlen(name);
1455
1456 /* We'll add a space after the name to respect the log format */
1457 free(global.log_send_hostname);
1458 global.log_send_hostname = malloc(len + 2);
1459 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1460 }
Kevinm48936af2010-12-22 16:08:21 +00001461 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1462 if (*(args[1]) == 0) {
1463 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1464 err_code |= ERR_ALERT | ERR_FATAL;
1465 goto out;
1466 }
1467 free(global.log_tag);
1468 global.log_tag = strdup(args[1]);
1469 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001470 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1471 if (global.spread_checks != 0) {
1472 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001473 err_code |= ERR_ALERT;
1474 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001475 }
1476 if (*(args[1]) == 0) {
1477 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001478 err_code |= ERR_ALERT | ERR_FATAL;
1479 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001480 }
1481 global.spread_checks = atol(args[1]);
1482 if (global.spread_checks < 0 || global.spread_checks > 50) {
1483 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001484 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001485 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001486 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001487 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1488 const char *err;
1489 unsigned int val;
1490
1491
1492 if (*(args[1]) == 0) {
1493 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1494 err_code |= ERR_ALERT | ERR_FATAL;
1495 goto out;
1496 }
1497
1498 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1499 if (err) {
1500 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1501 err_code |= ERR_ALERT | ERR_FATAL;
1502 }
1503 global.max_spread_checks = val;
1504 if (global.max_spread_checks < 0) {
1505 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1506 err_code |= ERR_ALERT | ERR_FATAL;
1507 }
1508 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001509 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1510#ifdef USE_CPU_AFFINITY
1511 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001512 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001513 unsigned long cpus = 0;
1514
1515 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001516 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001517 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001518 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001519 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001520 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001521 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001522 proc = atol(args[1]);
1523 if (proc >= 1 && proc <= LONGBITS)
1524 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001525 }
1526
1527 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001528 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",
1529 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
1532 }
1533
1534 cur_arg = 2;
1535 while (*args[cur_arg]) {
1536 unsigned int low, high;
1537
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001538 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001539 char *dash = strchr(args[cur_arg], '-');
1540
1541 low = high = str2uic(args[cur_arg]);
1542 if (dash)
1543 high = str2uic(dash + 1);
1544
1545 if (high < low) {
1546 unsigned int swap = low;
1547 low = high;
1548 high = swap;
1549 }
1550
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001551 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001552 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001553 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001554 err_code |= ERR_ALERT | ERR_FATAL;
1555 goto out;
1556 }
1557
1558 while (low <= high)
1559 cpus |= 1UL << low++;
1560 }
1561 else {
1562 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1563 file, linenum, args[0], args[cur_arg]);
1564 err_code |= ERR_ALERT | ERR_FATAL;
1565 goto out;
1566 }
1567 cur_arg++;
1568 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001569 for (i = 0; i < LONGBITS; i++)
1570 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001571 global.cpu_map[i] = cpus;
1572#else
1573 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1574 err_code |= ERR_ALERT | ERR_FATAL;
1575 goto out;
1576#endif
1577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001579 struct cfg_kw_list *kwl;
1580 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001581 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001582
1583 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1584 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1585 if (kwl->kw[index].section != CFG_GLOBAL)
1586 continue;
1587 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001588 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001589 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001590 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001591 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001592 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001593 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001594 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001595 err_code |= ERR_WARN;
1596 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001597 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001598 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001599 }
1600 }
1601 }
1602
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001604 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001606
Willy Tarreau058e9072009-07-20 09:30:05 +02001607 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001608 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001609 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001610}
1611
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001612void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001613{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001614 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615 defproxy.mode = PR_MODE_TCP;
1616 defproxy.state = PR_STNEW;
1617 defproxy.maxconn = cfg_maxpconn;
1618 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001619 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001620
Simon Horman66183002013-02-23 10:16:43 +09001621 defproxy.defsrv.check.inter = DEF_CHKINTR;
1622 defproxy.defsrv.check.fastinter = 0;
1623 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001624 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1625 defproxy.defsrv.agent.fastinter = 0;
1626 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001627 defproxy.defsrv.check.rise = DEF_RISETIME;
1628 defproxy.defsrv.check.fall = DEF_FALLTIME;
1629 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1630 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001631 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001632 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001633 defproxy.defsrv.maxqueue = 0;
1634 defproxy.defsrv.minconn = 0;
1635 defproxy.defsrv.maxconn = 0;
1636 defproxy.defsrv.slowstart = 0;
1637 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1638 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1639 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001640
1641 defproxy.email_alert.level = LOG_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001642}
1643
Willy Tarreauade5ec42010-01-28 19:33:49 +01001644
Willy Tarreau63af98d2014-05-18 08:11:41 +02001645/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1646 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1647 * ERR_FATAL in case of error.
1648 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001649static int create_cond_regex_rule(const char *file, int line,
1650 struct proxy *px, int dir, int action, int flags,
1651 const char *cmd, const char *reg, const char *repl,
1652 const char **cond_start)
1653{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001654 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001655 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001656 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001657 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001658 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001659 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001660 int cs;
1661 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001662
1663 if (px == &defproxy) {
1664 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001665 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001666 goto err;
1667 }
1668
1669 if (*reg == 0) {
1670 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001671 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001672 goto err;
1673 }
1674
1675 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001676 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001677
Willy Tarreau5321c422010-01-28 20:35:13 +01001678 if (cond_start &&
1679 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001680 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1681 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1682 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001683 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001684 goto err;
1685 }
1686 }
1687 else if (cond_start && **cond_start) {
1688 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1689 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001690 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001691 goto err;
1692 }
1693
Willy Tarreau63af98d2014-05-18 08:11:41 +02001694 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001695 (dir == SMP_OPT_DIR_REQ) ?
1696 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1697 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1698 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001699
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001700 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001701 if (!preg) {
1702 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001703 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001704 goto err;
1705 }
1706
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001707 cs = !(flags & REG_ICASE);
1708 cap = !(flags & REG_NOSUB);
1709 error = NULL;
1710 if (!regex_comp(reg, preg, cs, cap, &error)) {
1711 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1712 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001713 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001714 goto err;
1715 }
1716
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001717 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001718 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001719 if (repl && err) {
1720 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1721 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001722 ret_code |= ERR_ALERT | ERR_FATAL;
1723 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001724 }
1725
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001726 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001727 ret_code |= ERR_WARN;
1728
1729 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001730
Willy Tarreau63af98d2014-05-18 08:11:41 +02001731 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001732 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001733 err:
1734 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001735 free(errmsg);
1736 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001737}
1738
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001740 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001741 * Returns the error code, 0 if OK, or any combination of :
1742 * - ERR_ABORT: must abort ASAP
1743 * - ERR_FATAL: we can continue parsing but not start the service
1744 * - ERR_WARN: a warning has been emitted
1745 * - ERR_ALERT: an alert has been emitted
1746 * Only the two first ones can stop processing, the two others are just
1747 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001748 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001749int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1750{
1751 static struct peers *curpeers = NULL;
1752 struct peer *newpeer = NULL;
1753 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001754 struct bind_conf *bind_conf;
1755 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001756 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001757 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001758
1759 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001760 if (!*args[1]) {
1761 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001762 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001763 goto out;
1764 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001765
1766 err = invalid_char(args[1]);
1767 if (err) {
1768 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1769 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001770 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001771 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001772 }
1773
1774 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1775 /*
1776 * If there are two proxies with the same name only following
1777 * combinations are allowed:
1778 */
1779 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001780 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 +02001781 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001782 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001783 }
1784 }
1785
1786 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1787 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1788 err_code |= ERR_ALERT | ERR_ABORT;
1789 goto out;
1790 }
1791
1792 curpeers->next = peers;
1793 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001794 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001795 curpeers->conf.line = linenum;
1796 curpeers->last_change = now.tv_sec;
1797 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001798 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001799 }
1800 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001801 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001802 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001803 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001804
1805 if (!*args[2]) {
1806 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1807 file, linenum, args[0]);
1808 err_code |= ERR_ALERT | ERR_FATAL;
1809 goto out;
1810 }
1811
1812 err = invalid_char(args[1]);
1813 if (err) {
1814 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1815 file, linenum, *err, args[1]);
1816 err_code |= ERR_ALERT | ERR_FATAL;
1817 goto out;
1818 }
1819
1820 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1821 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1822 err_code |= ERR_ALERT | ERR_ABORT;
1823 goto out;
1824 }
1825
1826 /* the peers are linked backwards first */
1827 curpeers->count++;
1828 newpeer->next = curpeers->remote;
1829 curpeers->remote = newpeer;
1830 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001831 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001832 newpeer->conf.line = linenum;
1833
1834 newpeer->last_change = now.tv_sec;
1835 newpeer->id = strdup(args[1]);
1836
Willy Tarreau902636f2013-03-10 19:44:48 +01001837 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001838 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001839 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001840 err_code |= ERR_ALERT | ERR_FATAL;
1841 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001842 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001843
1844 proto = protocol_by_family(sk->ss_family);
1845 if (!proto || !proto->connect) {
1846 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1847 file, linenum, args[0], args[1]);
1848 err_code |= ERR_ALERT | ERR_FATAL;
1849 goto out;
1850 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001851
1852 if (port1 != port2) {
1853 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1854 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001855 err_code |= ERR_ALERT | ERR_FATAL;
1856 goto out;
1857 }
1858
Willy Tarreau2aa38802013-02-20 19:20:59 +01001859 if (!port1) {
1860 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1861 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001862 err_code |= ERR_ALERT | ERR_FATAL;
1863 goto out;
1864 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001865
Emeric Brun32da3c42010-09-23 18:39:19 +02001866 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001867 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001868 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001869 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001870
Emeric Brun32da3c42010-09-23 18:39:19 +02001871 if (strcmp(newpeer->id, localpeer) == 0) {
1872 /* Current is local peer, it define a frontend */
1873 newpeer->local = 1;
1874
1875 if (!curpeers->peers_fe) {
1876 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1877 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1878 err_code |= ERR_ALERT | ERR_ABORT;
1879 goto out;
1880 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001881
Willy Tarreau237250c2011-07-29 01:49:03 +02001882 init_new_proxy(curpeers->peers_fe);
1883 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001884 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001885 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1886 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01001887 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02001888
1889 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1890
Willy Tarreau902636f2013-03-10 19:44:48 +01001891 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1892 if (errmsg && *errmsg) {
1893 indent_msg(&errmsg, 2);
1894 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001895 }
1896 else
1897 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1898 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001899 err_code |= ERR_FATAL;
1900 goto out;
1901 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001902
1903 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001904 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001905 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1906 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02001907 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02001908 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001909 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01001910 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001911 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1912 global.maxsock += l->maxconn;
1913 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001914 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001915 else {
1916 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1917 file, linenum, args[0], args[1],
1918 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1919 err_code |= ERR_FATAL;
1920 goto out;
1921 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001922 }
1923 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001924 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
1925 curpeers->state = PR_STSTOPPED;
1926 }
1927 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
1928 curpeers->state = PR_STNEW;
1929 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001930 else if (*args[0] != 0) {
1931 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1932 err_code |= ERR_ALERT | ERR_FATAL;
1933 goto out;
1934 }
1935
1936out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001937 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001938 return err_code;
1939}
1940
Simon Horman0d16a402015-01-30 11:22:58 +09001941
1942/*
1943 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
1944 * Returns the error code, 0 if OK, or any combination of :
1945 * - ERR_ABORT: must abort ASAP
1946 * - ERR_FATAL: we can continue parsing but not start the service
1947 * - ERR_WARN: a warning has been emitted
1948 * - ERR_ALERT: an alert has been emitted
1949 * Only the two first ones can stop processing, the two others are just
1950 * indicators.
1951 */
1952int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
1953{
1954 static struct mailers *curmailers = NULL;
1955 struct mailer *newmailer = NULL;
1956 const char *err;
1957 int err_code = 0;
1958 char *errmsg = NULL;
1959
1960 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
1961 if (!*args[1]) {
1962 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
1963 err_code |= ERR_ALERT | ERR_ABORT;
1964 goto out;
1965 }
1966
1967 err = invalid_char(args[1]);
1968 if (err) {
1969 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1970 file, linenum, *err, args[0], args[1]);
1971 err_code |= ERR_ALERT | ERR_ABORT;
1972 goto out;
1973 }
1974
1975 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
1976 /*
1977 * If there are two proxies with the same name only following
1978 * combinations are allowed:
1979 */
1980 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001981 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 +09001982 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001983 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09001984 }
1985 }
1986
1987 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
1988 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1989 err_code |= ERR_ALERT | ERR_ABORT;
1990 goto out;
1991 }
1992
1993 curmailers->next = mailers;
1994 mailers = curmailers;
1995 curmailers->conf.file = strdup(file);
1996 curmailers->conf.line = linenum;
1997 curmailers->id = strdup(args[1]);
1998 }
1999 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2000 struct sockaddr_storage *sk;
2001 int port1, port2;
2002 struct protocol *proto;
2003
2004 if (!*args[2]) {
2005 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2006 file, linenum, args[0]);
2007 err_code |= ERR_ALERT | ERR_FATAL;
2008 goto out;
2009 }
2010
2011 err = invalid_char(args[1]);
2012 if (err) {
2013 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2014 file, linenum, *err, args[1]);
2015 err_code |= ERR_ALERT | ERR_FATAL;
2016 goto out;
2017 }
2018
2019 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2020 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2021 err_code |= ERR_ALERT | ERR_ABORT;
2022 goto out;
2023 }
2024
2025 /* the mailers are linked backwards first */
2026 curmailers->count++;
2027 newmailer->next = curmailers->mailer_list;
2028 curmailers->mailer_list = newmailer;
2029 newmailer->mailers = curmailers;
2030 newmailer->conf.file = strdup(file);
2031 newmailer->conf.line = linenum;
2032
2033 newmailer->id = strdup(args[1]);
2034
2035 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2036 if (!sk) {
2037 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2038 err_code |= ERR_ALERT | ERR_FATAL;
2039 goto out;
2040 }
2041
2042 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002043 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2044 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002045 file, linenum, args[0], args[1]);
2046 err_code |= ERR_ALERT | ERR_FATAL;
2047 goto out;
2048 }
2049
2050 if (port1 != port2) {
2051 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2052 file, linenum, args[0], args[1], args[2]);
2053 err_code |= ERR_ALERT | ERR_FATAL;
2054 goto out;
2055 }
2056
2057 if (!port1) {
2058 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2059 file, linenum, args[0], args[1], args[2]);
2060 err_code |= ERR_ALERT | ERR_FATAL;
2061 goto out;
2062 }
2063
2064 newmailer->addr = *sk;
2065 newmailer->proto = proto;
2066 newmailer->xprt = &raw_sock;
2067 newmailer->sock_init_arg = NULL;
2068 } /* neither "mailer" nor "mailers" */
2069 else if (*args[0] != 0) {
2070 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2071 err_code |= ERR_ALERT | ERR_FATAL;
2072 goto out;
2073 }
2074
2075out:
2076 free(errmsg);
2077 return err_code;
2078}
2079
Simon Horman9dc49962015-01-30 11:22:59 +09002080static void free_email_alert(struct proxy *p)
2081{
2082 free(p->email_alert.mailers.name);
2083 p->email_alert.mailers.name = NULL;
2084 free(p->email_alert.from);
2085 p->email_alert.from = NULL;
2086 free(p->email_alert.to);
2087 p->email_alert.to = NULL;
2088 free(p->email_alert.myhostname);
2089 p->email_alert.myhostname = NULL;
2090}
2091
Willy Tarreau3842f002009-06-14 11:39:52 +02002092int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002093{
2094 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002095 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002096 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002097 int rc;
2098 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002099 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002100 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002101 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002102 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002103 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104
Willy Tarreau977b8e42006-12-29 14:19:17 +01002105 if (!strcmp(args[0], "listen"))
2106 rc = PR_CAP_LISTEN;
2107 else if (!strcmp(args[0], "frontend"))
2108 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002109 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002110 rc = PR_CAP_BE | PR_CAP_RS;
2111 else if (!strcmp(args[0], "ruleset"))
2112 rc = PR_CAP_RS;
2113 else
2114 rc = PR_CAP_NONE;
2115
2116 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002117 if (!*args[1]) {
2118 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2119 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2120 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002121 err_code |= ERR_ALERT | ERR_ABORT;
2122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002123 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002124
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002125 err = invalid_char(args[1]);
2126 if (err) {
2127 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2128 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002129 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002130 }
2131
Willy Tarreau8f50b682015-05-26 11:45:02 +02002132 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2133 if (curproxy) {
2134 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2135 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2136 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002137 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002138 }
2139
Willy Tarreaubaaee002006-06-26 02:48:02 +02002140 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2141 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002142 err_code |= ERR_ALERT | ERR_ABORT;
2143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002144 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002145
Willy Tarreau97cb7802010-01-03 20:23:58 +01002146 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002147 curproxy->next = proxy;
2148 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002149 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2150 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002151 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002152 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002153 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002154 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002155
2156 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002157 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002158 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02002159
Willy Tarreau4348fad2012-09-20 16:48:07 +02002160 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2161
Willy Tarreau902636f2013-03-10 19:44:48 +01002162 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2163 if (errmsg && *errmsg) {
2164 indent_msg(&errmsg, 2);
2165 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002166 }
2167 else
2168 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2169 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002170 err_code |= ERR_FATAL;
2171 goto out;
2172 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002173
Willy Tarreau4348fad2012-09-20 16:48:07 +02002174 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002175 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002176 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002177 }
2178
2179 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002180 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002181 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002182
Willy Tarreaubaaee002006-06-26 02:48:02 +02002183 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002184 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002185 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002186 curproxy->no_options = defproxy.no_options;
2187 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002188 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002189 curproxy->except_net = defproxy.except_net;
2190 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002191 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002192 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002193
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002194 if (defproxy.fwdfor_hdr_len) {
2195 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2196 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2197 }
2198
Willy Tarreaub86db342009-11-30 11:50:16 +01002199 if (defproxy.orgto_hdr_len) {
2200 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2201 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2202 }
2203
Mark Lamourinec2247f02012-01-04 13:02:01 -05002204 if (defproxy.server_id_hdr_len) {
2205 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2206 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2207 }
2208
Willy Tarreau977b8e42006-12-29 14:19:17 +01002209 if (curproxy->cap & PR_CAP_FE) {
2210 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002211 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002212 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002213
2214 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002215 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2216 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002217
2218 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2219 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002220
Willy Tarreau977b8e42006-12-29 14:19:17 +01002221 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002222 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002223 curproxy->fullconn = defproxy.fullconn;
2224 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002225 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002226 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002227
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002228 if (defproxy.check_req) {
2229 curproxy->check_req = calloc(1, defproxy.check_len);
2230 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2231 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002232 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002234 if (defproxy.expect_str) {
2235 curproxy->expect_str = strdup(defproxy.expect_str);
2236 if (defproxy.expect_regex) {
2237 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002238 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2239 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002240 }
2241 }
2242
Willy Tarreau67402132012-05-31 20:40:20 +02002243 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002244 if (defproxy.cookie_name)
2245 curproxy->cookie_name = strdup(defproxy.cookie_name);
2246 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002247 if (defproxy.cookie_domain)
2248 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002249
Willy Tarreau31936852010-10-06 16:59:56 +02002250 if (defproxy.cookie_maxidle)
2251 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2252
2253 if (defproxy.cookie_maxlife)
2254 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2255
Emeric Brun647caf12009-06-30 17:57:00 +02002256 if (defproxy.rdp_cookie_name)
2257 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2258 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2259
Willy Tarreau01732802007-11-01 22:48:15 +01002260 if (defproxy.url_param_name)
2261 curproxy->url_param_name = strdup(defproxy.url_param_name);
2262 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002263
Benoitaffb4812009-03-25 13:02:10 +01002264 if (defproxy.hh_name)
2265 curproxy->hh_name = strdup(defproxy.hh_name);
2266 curproxy->hh_len = defproxy.hh_len;
2267 curproxy->hh_match_domain = defproxy.hh_match_domain;
2268
Willy Tarreauef9a3602012-12-08 22:29:20 +01002269 if (defproxy.conn_src.iface_name)
2270 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2271 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002272 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002273#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002274 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002275#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002278 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002279 if (defproxy.capture_name)
2280 curproxy->capture_name = strdup(defproxy.capture_name);
2281 curproxy->capture_namelen = defproxy.capture_namelen;
2282 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002284
Willy Tarreau977b8e42006-12-29 14:19:17 +01002285 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002286 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002287 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002288 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002289 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002290 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002291 curproxy->mon_net = defproxy.mon_net;
2292 curproxy->mon_mask = defproxy.mon_mask;
2293 if (defproxy.monitor_uri)
2294 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2295 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002296 if (defproxy.defbe.name)
2297 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002298
2299 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002300 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2301 if (curproxy->conf.logformat_string &&
2302 curproxy->conf.logformat_string != default_http_log_format &&
2303 curproxy->conf.logformat_string != default_tcp_log_format &&
2304 curproxy->conf.logformat_string != clf_http_log_format)
2305 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2306
2307 if (defproxy.conf.lfs_file) {
2308 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2309 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2310 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002311 }
2312
2313 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002314 curproxy->timeout.connect = defproxy.timeout.connect;
2315 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002316 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002317 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002318 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002319 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002320 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002321 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002322 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002323 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002324 }
2325
Willy Tarreaubaaee002006-06-26 02:48:02 +02002326 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002327 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002328
2329 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002330 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002331 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002332 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002333 LIST_INIT(&node->list);
2334 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2335 }
2336
Willy Tarreau62a61232013-04-12 18:13:46 +02002337 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2338 if (curproxy->conf.uniqueid_format_string)
2339 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2340
Willy Tarreau094af4e2015-01-07 15:03:42 +01002341 if (defproxy.log_tag)
2342 curproxy->log_tag = strdup(defproxy.log_tag);
2343
Willy Tarreau62a61232013-04-12 18:13:46 +02002344 if (defproxy.conf.uif_file) {
2345 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2346 curproxy->conf.uif_line = defproxy.conf.uif_line;
2347 }
William Lallemanda73203e2012-03-12 12:48:57 +01002348
2349 /* copy default header unique id */
2350 if (defproxy.header_unique_id)
2351 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2352
William Lallemand82fe75c2012-10-23 10:25:10 +02002353 /* default compression options */
2354 if (defproxy.comp != NULL) {
2355 curproxy->comp = calloc(1, sizeof(struct comp));
2356 curproxy->comp->algos = defproxy.comp->algos;
2357 curproxy->comp->types = defproxy.comp->types;
2358 }
2359
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002361 curproxy->conf.used_listener_id = EB_ROOT;
2362 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002363
Simon Horman98637e52014-06-20 12:30:16 +09002364 if (defproxy.check_path)
2365 curproxy->check_path = strdup(defproxy.check_path);
2366 if (defproxy.check_command)
2367 curproxy->check_command = strdup(defproxy.check_command);
2368
Simon Horman9dc49962015-01-30 11:22:59 +09002369 if (defproxy.email_alert.mailers.name)
2370 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2371 if (defproxy.email_alert.from)
2372 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2373 if (defproxy.email_alert.to)
2374 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2375 if (defproxy.email_alert.myhostname)
2376 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002377 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002378
Willy Tarreau93893792009-07-23 13:19:11 +02002379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002380 }
2381 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2382 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002383 /* FIXME-20070101: we should do this too at the end of the
2384 * config parsing to free all default values.
2385 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002386 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002387 free(defproxy.check_command);
2388 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002389 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002390 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002391 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002392 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002393 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002394 free(defproxy.capture_name);
2395 free(defproxy.monitor_uri);
2396 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002397 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002398 free(defproxy.fwdfor_hdr_name);
2399 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002400 free(defproxy.orgto_hdr_name);
2401 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002402 free(defproxy.server_id_hdr_name);
2403 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002404 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002405 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002406 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002407 free(defproxy.expect_regex);
2408 defproxy.expect_regex = NULL;
2409 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002410
Willy Tarreau62a61232013-04-12 18:13:46 +02002411 if (defproxy.conf.logformat_string != default_http_log_format &&
2412 defproxy.conf.logformat_string != default_tcp_log_format &&
2413 defproxy.conf.logformat_string != clf_http_log_format)
2414 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002415
Willy Tarreau62a61232013-04-12 18:13:46 +02002416 free(defproxy.conf.uniqueid_format_string);
2417 free(defproxy.conf.lfs_file);
2418 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002419 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002420 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002421
Willy Tarreaua534fea2008-08-03 12:19:50 +02002422 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002423 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002424
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 /* we cannot free uri_auth because it might already be used */
2426 init_default_instance();
2427 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002428 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2429 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002430 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002432 }
2433 else if (curproxy == NULL) {
2434 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002437 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002438
2439 /* update the current file and line being parsed */
2440 curproxy->conf.args.file = curproxy->conf.file;
2441 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002442
2443 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002444 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2445 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2446 if (err_code & ERR_FATAL)
2447 goto out;
2448 }
2449 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002450 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002451 int cur_arg;
2452
Willy Tarreaubaaee002006-06-26 02:48:02 +02002453 if (curproxy == &defproxy) {
2454 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002455 err_code |= ERR_ALERT | ERR_FATAL;
2456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002457 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002458 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002459 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460
Willy Tarreau24709282013-03-10 21:32:12 +01002461 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002462 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002467
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002468 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002469
2470 /* use default settings for unix sockets */
2471 bind_conf->ux.uid = global.unix_bind.ux.uid;
2472 bind_conf->ux.gid = global.unix_bind.ux.gid;
2473 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002474
2475 /* NOTE: the following line might create several listeners if there
2476 * are comma-separated IPs or port ranges. So all further processing
2477 * will have to be applied to all listeners created after last_listen.
2478 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002479 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2480 if (errmsg && *errmsg) {
2481 indent_msg(&errmsg, 2);
2482 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002483 }
2484 else
2485 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2486 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
2489 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002490
Willy Tarreau4348fad2012-09-20 16:48:07 +02002491 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2492 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002493 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002494 }
2495
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002496 cur_arg = 2;
2497 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002498 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002499 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002500 char *err;
2501
Willy Tarreau26982662012-09-12 23:17:10 +02002502 kw = bind_find_kw(args[cur_arg]);
2503 if (kw) {
2504 char *err = NULL;
2505 int code;
2506
2507 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002508 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2509 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002510 cur_arg += 1 + kw->skip ;
2511 err_code |= ERR_ALERT | ERR_FATAL;
2512 goto out;
2513 }
2514
Willy Tarreau4348fad2012-09-20 16:48:07 +02002515 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002516 err_code |= code;
2517
2518 if (code) {
2519 if (err && *err) {
2520 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002521 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002522 }
2523 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002524 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2525 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002526 if (code & ERR_FATAL) {
2527 free(err);
2528 cur_arg += 1 + kw->skip;
2529 goto out;
2530 }
2531 }
2532 free(err);
2533 cur_arg += 1 + kw->skip;
2534 continue;
2535 }
2536
Willy Tarreau8638f482012-09-18 18:01:17 +02002537 err = NULL;
2538 if (!bind_dumped) {
2539 bind_dump_kws(&err);
2540 indent_msg(&err, 4);
2541 bind_dumped = 1;
2542 }
2543
2544 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2545 file, linenum, args[0], args[1], args[cur_arg],
2546 err ? " Registered keywords :" : "", err ? err : "");
2547 free(err);
2548
Willy Tarreau93893792009-07-23 13:19:11 +02002549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002551 }
Willy Tarreau93893792009-07-23 13:19:11 +02002552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 }
2554 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002555 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2557 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002558 err_code |= ERR_ALERT | ERR_FATAL;
2559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002561 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002562 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002563
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 /* flush useless bits */
2565 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002568 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002569 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002570 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002571
Willy Tarreau1c47f852006-07-09 08:22:27 +02002572 if (!*args[1]) {
2573 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2574 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002575 err_code |= ERR_ALERT | ERR_FATAL;
2576 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002577 }
2578
Willy Tarreaua534fea2008-08-03 12:19:50 +02002579 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002580 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002581 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002582 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002583 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2584
Willy Tarreau93893792009-07-23 13:19:11 +02002585 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2588 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2589 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2590 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2591 else {
2592 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002593 err_code |= ERR_ALERT | ERR_FATAL;
2594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 }
2596 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002597 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002598 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002599
2600 if (curproxy == &defproxy) {
2601 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2602 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002605 }
2606
2607 if (!*args[1]) {
2608 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2609 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002610 err_code |= ERR_ALERT | ERR_FATAL;
2611 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002612 }
2613
2614 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002615 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02002616 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002617
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002618 if (curproxy->uuid <= 0) {
2619 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002620 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002621 err_code |= ERR_ALERT | ERR_FATAL;
2622 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002623 }
2624
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002625 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2626 if (node) {
2627 struct proxy *target = container_of(node, struct proxy, conf.id);
2628 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2629 file, linenum, proxy_type_str(curproxy), curproxy->id,
2630 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2631 err_code |= ERR_ALERT | ERR_FATAL;
2632 goto out;
2633 }
2634 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002635 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002636 else if (!strcmp(args[0], "description")) {
2637 int i, len=0;
2638 char *d;
2639
Cyril Bonté99ed3272010-01-24 23:29:44 +01002640 if (curproxy == &defproxy) {
2641 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2642 file, linenum, args[0]);
2643 err_code |= ERR_ALERT | ERR_FATAL;
2644 goto out;
2645 }
2646
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002647 if (!*args[1]) {
2648 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2649 file, linenum, args[0]);
2650 return -1;
2651 }
2652
Willy Tarreau348acfe2014-04-14 15:00:39 +02002653 for (i = 1; *args[i]; i++)
2654 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002655
2656 d = (char *)calloc(1, len);
2657 curproxy->desc = d;
2658
Willy Tarreau348acfe2014-04-14 15:00:39 +02002659 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2660 for (i = 2; *args[i]; i++)
2661 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002662
2663 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002664 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2665 curproxy->state = PR_STSTOPPED;
2666 }
2667 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2668 curproxy->state = PR_STNEW;
2669 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002670 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2671 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002672 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002673
2674 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002675 unsigned int low, high;
2676
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002677 if (strcmp(args[cur_arg], "all") == 0) {
2678 set = 0;
2679 break;
2680 }
2681 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002682 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002683 }
2684 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002685 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002686 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002687 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002688 char *dash = strchr(args[cur_arg], '-');
2689
2690 low = high = str2uic(args[cur_arg]);
2691 if (dash)
2692 high = str2uic(dash + 1);
2693
2694 if (high < low) {
2695 unsigned int swap = low;
2696 low = high;
2697 high = swap;
2698 }
2699
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002700 if (low < 1 || high > LONGBITS) {
2701 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2702 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002705 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002706 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002707 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002708 }
2709 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002710 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2711 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002712 err_code |= ERR_ALERT | ERR_FATAL;
2713 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002714 }
2715 cur_arg++;
2716 }
2717 curproxy->bind_proc = set;
2718 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002719 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002720 if (curproxy == &defproxy) {
2721 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002722 err_code |= ERR_ALERT | ERR_FATAL;
2723 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002724 }
2725
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002726 err = invalid_char(args[1]);
2727 if (err) {
2728 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2729 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002730 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002731 }
2732
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002733 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002734 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2735 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002736 err_code |= ERR_ALERT | ERR_FATAL;
2737 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002738 }
2739 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002740 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2741 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742
Willy Tarreau977b8e42006-12-29 14:19:17 +01002743 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002744 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002745
Willy Tarreaubaaee002006-06-26 02:48:02 +02002746 if (*(args[1]) == 0) {
2747 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2748 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002749 err_code |= ERR_ALERT | ERR_FATAL;
2750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002751 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002752
Willy Tarreau67402132012-05-31 20:40:20 +02002753 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002754 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002755 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002756 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002757 curproxy->cookie_name = strdup(args[1]);
2758 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002759
Willy Tarreaubaaee002006-06-26 02:48:02 +02002760 cur_arg = 2;
2761 while (*(args[cur_arg])) {
2762 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002763 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002764 }
2765 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002766 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002767 }
2768 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002769 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002770 }
2771 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002772 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002773 }
2774 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002775 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002776 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002777 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002778 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002779 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002780 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002781 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002783 else if (!strcmp(args[cur_arg], "httponly")) {
2784 curproxy->ck_opts |= PR_CK_HTTPONLY;
2785 }
2786 else if (!strcmp(args[cur_arg], "secure")) {
2787 curproxy->ck_opts |= PR_CK_SECURE;
2788 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002789 else if (!strcmp(args[cur_arg], "domain")) {
2790 if (!*args[cur_arg + 1]) {
2791 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2792 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002793 err_code |= ERR_ALERT | ERR_FATAL;
2794 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002795 }
2796
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002797 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002798 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002799 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2800 " dots nor does not start with a dot."
2801 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002802 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002803 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002804 }
2805
2806 err = invalid_domainchar(args[cur_arg + 1]);
2807 if (err) {
2808 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2809 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002810 err_code |= ERR_ALERT | ERR_FATAL;
2811 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002812 }
2813
Willy Tarreau68a897b2009-12-03 23:28:34 +01002814 if (!curproxy->cookie_domain) {
2815 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2816 } else {
2817 /* one domain was already specified, add another one by
2818 * building the string which will be returned along with
2819 * the cookie.
2820 */
2821 char *new_ptr;
2822 int new_len = strlen(curproxy->cookie_domain) +
2823 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2824 new_ptr = malloc(new_len);
2825 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2826 free(curproxy->cookie_domain);
2827 curproxy->cookie_domain = new_ptr;
2828 }
Willy Tarreau31936852010-10-06 16:59:56 +02002829 cur_arg++;
2830 }
2831 else if (!strcmp(args[cur_arg], "maxidle")) {
2832 unsigned int maxidle;
2833 const char *res;
2834
2835 if (!*args[cur_arg + 1]) {
2836 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2837 file, linenum, args[cur_arg]);
2838 err_code |= ERR_ALERT | ERR_FATAL;
2839 goto out;
2840 }
2841
2842 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2843 if (res) {
2844 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2845 file, linenum, *res, args[cur_arg]);
2846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
2848 }
2849 curproxy->cookie_maxidle = maxidle;
2850 cur_arg++;
2851 }
2852 else if (!strcmp(args[cur_arg], "maxlife")) {
2853 unsigned int maxlife;
2854 const char *res;
2855
2856 if (!*args[cur_arg + 1]) {
2857 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2858 file, linenum, args[cur_arg]);
2859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
2861 }
2862
2863 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2864 if (res) {
2865 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2866 file, linenum, *res, args[cur_arg]);
2867 err_code |= ERR_ALERT | ERR_FATAL;
2868 goto out;
2869 }
2870 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002871 cur_arg++;
2872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002873 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002874 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 +02002875 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002878 }
2879 cur_arg++;
2880 }
Willy Tarreau67402132012-05-31 20:40:20 +02002881 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002882 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2883 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002884 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002885 }
2886
Willy Tarreau67402132012-05-31 20:40:20 +02002887 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002888 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2889 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002890 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002891 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002892
Willy Tarreau67402132012-05-31 20:40:20 +02002893 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002894 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2895 file, linenum);
2896 err_code |= ERR_ALERT | ERR_FATAL;
2897 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002898 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09002899 else if (!strcmp(args[0], "email-alert")) {
2900 if (*(args[1]) == 0) {
2901 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2902 file, linenum, args[0]);
2903 err_code |= ERR_ALERT | ERR_FATAL;
2904 goto out;
2905 }
2906
2907 if (!strcmp(args[1], "from")) {
2908 if (*(args[1]) == 0) {
2909 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2910 file, linenum, args[1]);
2911 err_code |= ERR_ALERT | ERR_FATAL;
2912 goto out;
2913 }
2914 free(curproxy->email_alert.from);
2915 curproxy->email_alert.from = strdup(args[2]);
2916 }
2917 else if (!strcmp(args[1], "mailers")) {
2918 if (*(args[1]) == 0) {
2919 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2920 file, linenum, args[1]);
2921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
2923 }
2924 free(curproxy->email_alert.mailers.name);
2925 curproxy->email_alert.mailers.name = strdup(args[2]);
2926 }
2927 else if (!strcmp(args[1], "myhostname")) {
2928 if (*(args[1]) == 0) {
2929 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2930 file, linenum, args[1]);
2931 err_code |= ERR_ALERT | ERR_FATAL;
2932 goto out;
2933 }
2934 free(curproxy->email_alert.myhostname);
2935 curproxy->email_alert.myhostname = strdup(args[2]);
2936 }
Simon Horman64e34162015-02-06 11:11:57 +09002937 else if (!strcmp(args[1], "level")) {
2938 curproxy->email_alert.level = get_log_level(args[2]);
2939 if (curproxy->email_alert.level < 0) {
2940 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
2941 file, linenum, args[1], args[2]);
2942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
2944 }
2945 }
Simon Horman9dc49962015-01-30 11:22:59 +09002946 else if (!strcmp(args[1], "to")) {
2947 if (*(args[1]) == 0) {
2948 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2949 file, linenum, args[1]);
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952 }
2953 free(curproxy->email_alert.to);
2954 curproxy->email_alert.to = strdup(args[2]);
2955 }
2956 else {
2957 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
2958 file, linenum, args[1]);
2959 err_code |= ERR_ALERT | ERR_FATAL;
2960 goto out;
2961 }
Simon Horman64e34162015-02-06 11:11:57 +09002962 /* Indicate that the email_alert is at least partially configured */
2963 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09002964 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09002965 else if (!strcmp(args[0], "external-check")) {
2966 if (*(args[1]) == 0) {
2967 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2968 file, linenum, args[0]);
2969 err_code |= ERR_ALERT | ERR_FATAL;
2970 goto out;
2971 }
2972
2973 if (!strcmp(args[1], "command")) {
2974 if (*(args[1]) == 0) {
2975 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2976 file, linenum, args[1]);
2977 err_code |= ERR_ALERT | ERR_FATAL;
2978 goto out;
2979 }
2980 free(curproxy->check_command);
2981 curproxy->check_command = strdup(args[2]);
2982 }
2983 else if (!strcmp(args[1], "path")) {
2984 if (*(args[1]) == 0) {
2985 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2986 file, linenum, args[1]);
2987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
2989 }
2990 free(curproxy->check_path);
2991 curproxy->check_path = strdup(args[2]);
2992 }
2993 else {
2994 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
2995 file, linenum, args[1]);
2996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
2998 }
2999 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003000 else if (!strcmp(args[0], "persist")) { /* persist */
3001 if (*(args[1]) == 0) {
3002 Alert("parsing [%s:%d] : missing persist method.\n",
3003 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003006 }
3007
3008 if (!strncmp(args[1], "rdp-cookie", 10)) {
3009 curproxy->options2 |= PR_O2_RDPC_PRST;
3010
Emeric Brunb982a3d2010-01-04 15:45:53 +01003011 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003012 const char *beg, *end;
3013
3014 beg = args[1] + 11;
3015 end = strchr(beg, ')');
3016
3017 if (!end || end == beg) {
3018 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3019 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003020 err_code |= ERR_ALERT | ERR_FATAL;
3021 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003022 }
3023
3024 free(curproxy->rdp_cookie_name);
3025 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3026 curproxy->rdp_cookie_len = end-beg;
3027 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003028 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003029 free(curproxy->rdp_cookie_name);
3030 curproxy->rdp_cookie_name = strdup("msts");
3031 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3032 }
3033 else { /* syntax */
3034 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3035 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003038 }
3039 }
3040 else {
3041 Alert("parsing [%s:%d] : unknown persist method.\n",
3042 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003045 }
3046 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003047 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003048 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003049
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003050 if (curproxy == &defproxy) {
3051 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3052 err_code |= ERR_ALERT | ERR_FATAL;
3053 goto out;
3054 }
3055
Willy Tarreau977b8e42006-12-29 14:19:17 +01003056 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003057 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003058
Willy Tarreaubaaee002006-06-26 02:48:02 +02003059 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003060 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003062 err_code |= ERR_ALERT | ERR_FATAL;
3063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003064 }
3065 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003066 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067 curproxy->appsession_name = strdup(args[1]);
3068 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3069 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003070 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3071 if (err) {
3072 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3073 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003074 err_code |= ERR_ALERT | ERR_FATAL;
3075 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003076 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003077 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003078
Willy Tarreau51041c72007-09-09 21:56:53 +02003079 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3080 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003081 err_code |= ERR_ALERT | ERR_ABORT;
3082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003084
3085 cur_arg = 6;
3086 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003087 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3088 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003089 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003090 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003091 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003092 } else if (!strcmp(args[cur_arg], "prefix")) {
3093 curproxy->options2 |= PR_O2_AS_PFX;
3094 } else if (!strcmp(args[cur_arg], "mode")) {
3095 if (!*args[cur_arg + 1]) {
3096 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3097 file, linenum, args[0], args[cur_arg]);
3098 err_code |= ERR_ALERT | ERR_FATAL;
3099 goto out;
3100 }
3101
3102 cur_arg++;
3103 if (!strcmp(args[cur_arg], "query-string")) {
3104 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3105 curproxy->options2 |= PR_O2_AS_M_QS;
3106 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3107 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3108 curproxy->options2 |= PR_O2_AS_M_PP;
3109 } else {
3110 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3111 err_code |= ERR_ALERT | ERR_FATAL;
3112 goto out;
3113 }
3114 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003115 cur_arg++;
3116 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003117 } /* Url App Session */
3118 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003119 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003120 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003121
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003123 if (curproxy == &defproxy) {
3124 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
3127 }
3128
Willy Tarreaubaaee002006-06-26 02:48:02 +02003129 if (*(args[4]) == 0) {
3130 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3131 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003132 err_code |= ERR_ALERT | ERR_FATAL;
3133 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003134 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003135 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136 curproxy->capture_name = strdup(args[2]);
3137 curproxy->capture_namelen = strlen(curproxy->capture_name);
3138 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003139 curproxy->to_log |= LW_COOKIE;
3140 }
3141 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3142 struct cap_hdr *hdr;
3143
3144 if (curproxy == &defproxy) {
3145 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 +02003146 err_code |= ERR_ALERT | ERR_FATAL;
3147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 }
3149
3150 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3151 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3152 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 }
3156
3157 hdr = calloc(sizeof(struct cap_hdr), 1);
3158 hdr->next = curproxy->req_cap;
3159 hdr->name = strdup(args[3]);
3160 hdr->namelen = strlen(args[3]);
3161 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003162 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003163 hdr->index = curproxy->nb_req_cap++;
3164 curproxy->req_cap = hdr;
3165 curproxy->to_log |= LW_REQHDR;
3166 }
3167 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3168 struct cap_hdr *hdr;
3169
3170 if (curproxy == &defproxy) {
3171 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 +02003172 err_code |= ERR_ALERT | ERR_FATAL;
3173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003174 }
3175
3176 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3177 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3178 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003179 err_code |= ERR_ALERT | ERR_FATAL;
3180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 }
3182 hdr = calloc(sizeof(struct cap_hdr), 1);
3183 hdr->next = curproxy->rsp_cap;
3184 hdr->name = strdup(args[3]);
3185 hdr->namelen = strlen(args[3]);
3186 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003187 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 hdr->index = curproxy->nb_rsp_cap++;
3189 curproxy->rsp_cap = hdr;
3190 curproxy->to_log |= LW_RSPHDR;
3191 }
3192 else {
3193 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3194 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003195 err_code |= ERR_ALERT | ERR_FATAL;
3196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003197 }
3198 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003200 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003201 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003202
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 if (*(args[1]) == 0) {
3204 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3205 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 }
3209 curproxy->conn_retries = atol(args[1]);
3210 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003211 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003212 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003213
3214 if (curproxy == &defproxy) {
3215 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
3218 }
3219
Willy Tarreau20b0de52012-12-24 15:45:22 +01003220 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3221 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3222 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3223 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003224 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003225 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3226 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 +01003227 file, linenum, args[0]);
3228 err_code |= ERR_WARN;
3229 }
3230
Willy Tarreauff011f22011-01-06 17:51:27 +01003231 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003232
Willy Tarreauff011f22011-01-06 17:51:27 +01003233 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003234 err_code |= ERR_ALERT | ERR_ABORT;
3235 goto out;
3236 }
3237
Willy Tarreau5002f572014-04-23 01:32:02 +02003238 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003239 err_code |= warnif_cond_conflicts(rule->cond,
3240 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3241 file, linenum);
3242
Willy Tarreauff011f22011-01-06 17:51:27 +01003243 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003244 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003245 else if (!strcmp(args[0], "http-response")) { /* response access control */
3246 struct http_res_rule *rule;
3247
3248 if (curproxy == &defproxy) {
3249 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
3252 }
3253
3254 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3255 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3256 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3257 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3258 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3259 file, linenum, args[0]);
3260 err_code |= ERR_WARN;
3261 }
3262
3263 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3264
3265 if (!rule) {
3266 err_code |= ERR_ALERT | ERR_ABORT;
3267 goto out;
3268 }
3269
3270 err_code |= warnif_cond_conflicts(rule->cond,
3271 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3272 file, linenum);
3273
3274 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3275 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003276 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3277 /* set the header name and length into the proxy structure */
3278 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3279 err_code |= ERR_WARN;
3280
3281 if (!*args[1]) {
3282 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3283 file, linenum, args[0]);
3284 err_code |= ERR_ALERT | ERR_FATAL;
3285 goto out;
3286 }
3287
3288 /* set the desired header name */
3289 free(curproxy->server_id_hdr_name);
3290 curproxy->server_id_hdr_name = strdup(args[1]);
3291 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3292 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003293 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003294 struct http_req_rule *rule;
3295
Willy Tarreaub099aca2008-10-12 17:26:37 +02003296 if (curproxy == &defproxy) {
3297 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_ALERT | ERR_FATAL;
3299 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003300 }
3301
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003302 /* emulate "block" using "http-request block". Since these rules are supposed to
3303 * be processed before all http-request rules, we put them into their own list
3304 * and will insert them at the end.
3305 */
3306 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3307 if (!rule) {
3308 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003309 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003310 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003311 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3312 err_code |= warnif_cond_conflicts(rule->cond,
3313 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3314 file, linenum);
3315 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003316
3317 if (!already_warned(WARN_BLOCK_DEPRECATED))
3318 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]);
3319
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003320 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003321 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003322 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003323
Cyril Bonté99ed3272010-01-24 23:29:44 +01003324 if (curproxy == &defproxy) {
3325 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3326 err_code |= ERR_ALERT | ERR_FATAL;
3327 goto out;
3328 }
3329
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003330 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003331 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3332 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003333 err_code |= ERR_ALERT | ERR_FATAL;
3334 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003335 }
3336
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003337 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003338 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003339 err_code |= warnif_cond_conflicts(rule->cond,
3340 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3341 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003342 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003343 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003344 struct switching_rule *rule;
3345
Willy Tarreaub099aca2008-10-12 17:26:37 +02003346 if (curproxy == &defproxy) {
3347 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003348 err_code |= ERR_ALERT | ERR_FATAL;
3349 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003350 }
3351
Willy Tarreau55ea7572007-06-17 19:56:27 +02003352 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003353 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003354
3355 if (*(args[1]) == 0) {
3356 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003359 }
3360
Willy Tarreauf51658d2014-04-23 01:21:56 +02003361 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3362 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3363 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3364 file, linenum, errmsg);
3365 err_code |= ERR_ALERT | ERR_FATAL;
3366 goto out;
3367 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003368
Willy Tarreauf51658d2014-04-23 01:21:56 +02003369 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003370 }
3371
3372 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3373 rule->cond = cond;
3374 rule->be.name = strdup(args[1]);
3375 LIST_INIT(&rule->list);
3376 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3377 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003378 else if (strcmp(args[0], "use-server") == 0) {
3379 struct server_rule *rule;
3380
3381 if (curproxy == &defproxy) {
3382 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3383 err_code |= ERR_ALERT | ERR_FATAL;
3384 goto out;
3385 }
3386
3387 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3388 err_code |= ERR_WARN;
3389
3390 if (*(args[1]) == 0) {
3391 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3392 err_code |= ERR_ALERT | ERR_FATAL;
3393 goto out;
3394 }
3395
3396 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3397 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3398 file, linenum, args[0]);
3399 err_code |= ERR_ALERT | ERR_FATAL;
3400 goto out;
3401 }
3402
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003403 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3404 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3405 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
3408 }
3409
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003410 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003411
3412 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3413 rule->cond = cond;
3414 rule->srv.name = strdup(args[1]);
3415 LIST_INIT(&rule->list);
3416 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3417 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3418 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003419 else if ((!strcmp(args[0], "force-persist")) ||
3420 (!strcmp(args[0], "ignore-persist"))) {
3421 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003422
3423 if (curproxy == &defproxy) {
3424 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3425 err_code |= ERR_ALERT | ERR_FATAL;
3426 goto out;
3427 }
3428
3429 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3430 err_code |= ERR_WARN;
3431
Willy Tarreauef6494c2010-01-28 17:12:36 +01003432 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003433 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3434 file, linenum, args[0]);
3435 err_code |= ERR_ALERT | ERR_FATAL;
3436 goto out;
3437 }
3438
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003439 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3440 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3441 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003442 err_code |= ERR_ALERT | ERR_FATAL;
3443 goto out;
3444 }
3445
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003446 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3447 * where force-persist is applied.
3448 */
3449 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003450
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003451 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003452 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003453 if (!strcmp(args[0], "force-persist")) {
3454 rule->type = PERSIST_TYPE_FORCE;
3455 } else {
3456 rule->type = PERSIST_TYPE_IGNORE;
3457 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003458 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003459 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003460 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003461 else if (!strcmp(args[0], "stick-table")) {
3462 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003463 struct proxy *other;
3464
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003465 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003466 if (other) {
3467 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3468 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3469 err_code |= ERR_ALERT | ERR_FATAL;
3470 goto out;
3471 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003472
Emeric Brun32da3c42010-09-23 18:39:19 +02003473 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003474 curproxy->table.type = (unsigned int)-1;
3475 while (*args[myidx]) {
3476 const char *err;
3477
3478 if (strcmp(args[myidx], "size") == 0) {
3479 myidx++;
3480 if (!*(args[myidx])) {
3481 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3482 file, linenum, args[myidx-1]);
3483 err_code |= ERR_ALERT | ERR_FATAL;
3484 goto out;
3485 }
3486 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3487 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3488 file, linenum, *err, args[myidx-1]);
3489 err_code |= ERR_ALERT | ERR_FATAL;
3490 goto out;
3491 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003492 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003493 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003494 else if (strcmp(args[myidx], "peers") == 0) {
3495 myidx++;
Godbach50523162013-12-11 19:48:57 +08003496 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003497 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3498 file, linenum, args[myidx-1]);
3499 err_code |= ERR_ALERT | ERR_FATAL;
3500 goto out;
Godbach50523162013-12-11 19:48:57 +08003501 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003502 curproxy->table.peers.name = strdup(args[myidx++]);
3503 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003504 else if (strcmp(args[myidx], "expire") == 0) {
3505 myidx++;
3506 if (!*(args[myidx])) {
3507 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3508 file, linenum, args[myidx-1]);
3509 err_code |= ERR_ALERT | ERR_FATAL;
3510 goto out;
3511 }
3512 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3513 if (err) {
3514 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3515 file, linenum, *err, args[myidx-1]);
3516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
3518 }
3519 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003520 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003521 }
3522 else if (strcmp(args[myidx], "nopurge") == 0) {
3523 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003524 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003525 }
3526 else if (strcmp(args[myidx], "type") == 0) {
3527 myidx++;
3528 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3529 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3530 file, linenum, args[myidx]);
3531 err_code |= ERR_ALERT | ERR_FATAL;
3532 goto out;
3533 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003534 /* myidx already points to next arg */
3535 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003536 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003537 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003538 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003539
3540 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003541 nw = args[myidx];
3542 while (*nw) {
3543 /* the "store" keyword supports a comma-separated list */
3544 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003545 sa = NULL; /* store arg */
3546 while (*nw && *nw != ',') {
3547 if (*nw == '(') {
3548 *nw = 0;
3549 sa = ++nw;
3550 while (*nw != ')') {
3551 if (!*nw) {
3552 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3553 file, linenum, args[0], cw);
3554 err_code |= ERR_ALERT | ERR_FATAL;
3555 goto out;
3556 }
3557 nw++;
3558 }
3559 *nw = '\0';
3560 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003561 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003562 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003563 if (*nw)
3564 *nw++ = '\0';
3565 type = stktable_get_data_type(cw);
3566 if (type < 0) {
3567 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3568 file, linenum, args[0], cw);
3569 err_code |= ERR_ALERT | ERR_FATAL;
3570 goto out;
3571 }
Willy Tarreauac782882010-06-20 10:41:54 +02003572
3573 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3574 switch (err) {
3575 case PE_NONE: break;
3576 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003577 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3578 file, linenum, args[0], cw);
3579 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003580 break;
3581
3582 case PE_ARG_MISSING:
3583 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3584 file, linenum, args[0], cw);
3585 err_code |= ERR_ALERT | ERR_FATAL;
3586 goto out;
3587
3588 case PE_ARG_NOT_USED:
3589 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3590 file, linenum, args[0], cw);
3591 err_code |= ERR_ALERT | ERR_FATAL;
3592 goto out;
3593
3594 default:
3595 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3596 file, linenum, args[0], cw);
3597 err_code |= ERR_ALERT | ERR_FATAL;
3598 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003599 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003600 }
3601 myidx++;
3602 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003603 else {
3604 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3605 file, linenum, args[myidx]);
3606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003608 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003609 }
3610
3611 if (!curproxy->table.size) {
3612 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3613 file, linenum);
3614 err_code |= ERR_ALERT | ERR_FATAL;
3615 goto out;
3616 }
3617
3618 if (curproxy->table.type == (unsigned int)-1) {
3619 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3620 file, linenum);
3621 err_code |= ERR_ALERT | ERR_FATAL;
3622 goto out;
3623 }
3624 }
3625 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003626 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003627 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003628 int myidx = 0;
3629 const char *name = NULL;
3630 int flags;
3631
3632 if (curproxy == &defproxy) {
3633 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3634 err_code |= ERR_ALERT | ERR_FATAL;
3635 goto out;
3636 }
3637
3638 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3639 err_code |= ERR_WARN;
3640 goto out;
3641 }
3642
3643 myidx++;
3644 if ((strcmp(args[myidx], "store") == 0) ||
3645 (strcmp(args[myidx], "store-request") == 0)) {
3646 myidx++;
3647 flags = STK_IS_STORE;
3648 }
3649 else if (strcmp(args[myidx], "store-response") == 0) {
3650 myidx++;
3651 flags = STK_IS_STORE | STK_ON_RSP;
3652 }
3653 else if (strcmp(args[myidx], "match") == 0) {
3654 myidx++;
3655 flags = STK_IS_MATCH;
3656 }
3657 else if (strcmp(args[myidx], "on") == 0) {
3658 myidx++;
3659 flags = STK_IS_MATCH | STK_IS_STORE;
3660 }
3661 else {
3662 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
3665 }
3666
3667 if (*(args[myidx]) == 0) {
3668 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3669 err_code |= ERR_ALERT | ERR_FATAL;
3670 goto out;
3671 }
3672
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003673 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003674 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003675 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003676 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003677 err_code |= ERR_ALERT | ERR_FATAL;
3678 goto out;
3679 }
3680
3681 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003682 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3683 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3684 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003685 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003686 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003687 goto out;
3688 }
3689 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003690 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3691 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3692 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003693 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003694 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003695 goto out;
3696 }
3697 }
3698
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003699 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003700 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003701
Emeric Brunb982a3d2010-01-04 15:45:53 +01003702 if (strcmp(args[myidx], "table") == 0) {
3703 myidx++;
3704 name = args[myidx++];
3705 }
3706
Willy Tarreauef6494c2010-01-28 17:12:36 +01003707 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003708 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3709 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3710 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003711 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003712 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003713 goto out;
3714 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003715 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003716 else if (*(args[myidx])) {
3717 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3718 file, linenum, args[0], args[myidx]);
3719 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003720 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003721 goto out;
3722 }
Emeric Brun97679e72010-09-23 17:56:44 +02003723 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003724 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003725 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003726 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003727
Emeric Brunb982a3d2010-01-04 15:45:53 +01003728 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3729 rule->cond = cond;
3730 rule->expr = expr;
3731 rule->flags = flags;
3732 rule->table.name = name ? strdup(name) : NULL;
3733 LIST_INIT(&rule->list);
3734 if (flags & STK_ON_RSP)
3735 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3736 else
3737 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3738 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003739 else if (!strcmp(args[0], "stats")) {
3740 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3741 curproxy->uri_auth = NULL; /* we must detach from the default config */
3742
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003743 if (!*args[1]) {
3744 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003745 } else if (!strcmp(args[1], "admin")) {
3746 struct stats_admin_rule *rule;
3747
3748 if (curproxy == &defproxy) {
3749 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3750 err_code |= ERR_ALERT | ERR_FATAL;
3751 goto out;
3752 }
3753
3754 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3755 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3756 err_code |= ERR_ALERT | ERR_ABORT;
3757 goto out;
3758 }
3759
3760 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3761 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3762 file, linenum, args[0], args[1]);
3763 err_code |= ERR_ALERT | ERR_FATAL;
3764 goto out;
3765 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003766 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3767 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3768 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003769 err_code |= ERR_ALERT | ERR_FATAL;
3770 goto out;
3771 }
3772
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003773 err_code |= warnif_cond_conflicts(cond,
3774 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3775 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003776
3777 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3778 rule->cond = cond;
3779 LIST_INIT(&rule->list);
3780 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 } else if (!strcmp(args[1], "uri")) {
3782 if (*(args[2]) == 0) {
3783 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003784 err_code |= ERR_ALERT | ERR_FATAL;
3785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003786 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3787 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_ALERT | ERR_ABORT;
3789 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003790 }
3791 } else if (!strcmp(args[1], "realm")) {
3792 if (*(args[2]) == 0) {
3793 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003794 err_code |= ERR_ALERT | ERR_FATAL;
3795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003796 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3797 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003798 err_code |= ERR_ALERT | ERR_ABORT;
3799 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003800 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003801 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003802 unsigned interval;
3803
3804 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3805 if (err) {
3806 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3807 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003808 err_code |= ERR_ALERT | ERR_FATAL;
3809 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003810 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3811 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003812 err_code |= ERR_ALERT | ERR_ABORT;
3813 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003814 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003815 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003816 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003817
3818 if (curproxy == &defproxy) {
3819 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3820 err_code |= ERR_ALERT | ERR_FATAL;
3821 goto out;
3822 }
3823
3824 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3825 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3826 err_code |= ERR_ALERT | ERR_ABORT;
3827 goto out;
3828 }
3829
Willy Tarreauff011f22011-01-06 17:51:27 +01003830 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3831 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003832 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3833 file, linenum, args[0]);
3834 err_code |= ERR_WARN;
3835 }
3836
Willy Tarreauff011f22011-01-06 17:51:27 +01003837 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003838
Willy Tarreauff011f22011-01-06 17:51:27 +01003839 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003840 err_code |= ERR_ALERT | ERR_ABORT;
3841 goto out;
3842 }
3843
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003844 err_code |= warnif_cond_conflicts(rule->cond,
3845 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3846 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003847 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003848
Willy Tarreaubaaee002006-06-26 02:48:02 +02003849 } else if (!strcmp(args[1], "auth")) {
3850 if (*(args[2]) == 0) {
3851 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003852 err_code |= ERR_ALERT | ERR_FATAL;
3853 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003854 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3855 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003856 err_code |= ERR_ALERT | ERR_ABORT;
3857 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003858 }
3859 } else if (!strcmp(args[1], "scope")) {
3860 if (*(args[2]) == 0) {
3861 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003864 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3865 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003866 err_code |= ERR_ALERT | ERR_ABORT;
3867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 }
3869 } else if (!strcmp(args[1], "enable")) {
3870 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3871 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003872 err_code |= ERR_ALERT | ERR_ABORT;
3873 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003874 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003875 } else if (!strcmp(args[1], "hide-version")) {
3876 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3877 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003878 err_code |= ERR_ALERT | ERR_ABORT;
3879 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003880 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003881 } else if (!strcmp(args[1], "show-legends")) {
3882 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3883 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3884 err_code |= ERR_ALERT | ERR_ABORT;
3885 goto out;
3886 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003887 } else if (!strcmp(args[1], "show-node")) {
3888
3889 if (*args[2]) {
3890 int i;
3891 char c;
3892
3893 for (i=0; args[2][i]; i++) {
3894 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003895 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3896 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003897 break;
3898 }
3899
3900 if (!i || args[2][i]) {
3901 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3902 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3903 file, linenum, args[0], args[1]);
3904 err_code |= ERR_ALERT | ERR_FATAL;
3905 goto out;
3906 }
3907 }
3908
3909 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3910 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3911 err_code |= ERR_ALERT | ERR_ABORT;
3912 goto out;
3913 }
3914 } else if (!strcmp(args[1], "show-desc")) {
3915 char *desc = NULL;
3916
3917 if (*args[2]) {
3918 int i, len=0;
3919 char *d;
3920
Willy Tarreau348acfe2014-04-14 15:00:39 +02003921 for (i = 2; *args[i]; i++)
3922 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003923
3924 desc = d = (char *)calloc(1, len);
3925
Willy Tarreau348acfe2014-04-14 15:00:39 +02003926 d += snprintf(d, desc + len - d, "%s", args[2]);
3927 for (i = 3; *args[i]; i++)
3928 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003929 }
3930
3931 if (!*args[2] && !global.desc)
3932 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3933 file, linenum, args[1]);
3934 else {
3935 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3936 free(desc);
3937 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3938 err_code |= ERR_ALERT | ERR_ABORT;
3939 goto out;
3940 }
3941 free(desc);
3942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003943 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003944stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003945 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 +01003946 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003949 }
3950 }
3951 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003952 int optnum;
3953
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003954 if (*(args[1]) == '\0') {
3955 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3956 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003959 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003960
3961 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3962 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003963 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3964 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3965 file, linenum, cfg_opts[optnum].name);
3966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
3968 }
Willy Tarreau93893792009-07-23 13:19:11 +02003969 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3970 err_code |= ERR_WARN;
3971 goto out;
3972 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003973
Willy Tarreau3842f002009-06-14 11:39:52 +02003974 curproxy->no_options &= ~cfg_opts[optnum].val;
3975 curproxy->options &= ~cfg_opts[optnum].val;
3976
3977 switch (kwm) {
3978 case KWM_STD:
3979 curproxy->options |= cfg_opts[optnum].val;
3980 break;
3981 case KWM_NO:
3982 curproxy->no_options |= cfg_opts[optnum].val;
3983 break;
3984 case KWM_DEF: /* already cleared */
3985 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003986 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003987
Willy Tarreau93893792009-07-23 13:19:11 +02003988 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003989 }
3990 }
3991
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003992 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3993 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003994 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3995 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3996 file, linenum, cfg_opts2[optnum].name);
3997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
3999 }
Willy Tarreau93893792009-07-23 13:19:11 +02004000 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4001 err_code |= ERR_WARN;
4002 goto out;
4003 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004004
Willy Tarreau3842f002009-06-14 11:39:52 +02004005 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4006 curproxy->options2 &= ~cfg_opts2[optnum].val;
4007
4008 switch (kwm) {
4009 case KWM_STD:
4010 curproxy->options2 |= cfg_opts2[optnum].val;
4011 break;
4012 case KWM_NO:
4013 curproxy->no_options2 |= cfg_opts2[optnum].val;
4014 break;
4015 case KWM_DEF: /* already cleared */
4016 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004017 }
Willy Tarreau93893792009-07-23 13:19:11 +02004018 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004019 }
4020 }
4021
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004022 /* HTTP options override each other. They can be cancelled using
4023 * "no option xxx" which only switches to default mode if the mode
4024 * was this one (useful for cancelling options set in defaults
4025 * sections).
4026 */
4027 if (strcmp(args[1], "httpclose") == 0) {
4028 if (kwm == KWM_STD) {
4029 curproxy->options &= ~PR_O_HTTP_MODE;
4030 curproxy->options |= PR_O_HTTP_PCL;
4031 goto out;
4032 }
4033 else if (kwm == KWM_NO) {
4034 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4035 curproxy->options &= ~PR_O_HTTP_MODE;
4036 goto out;
4037 }
4038 }
4039 else if (strcmp(args[1], "forceclose") == 0) {
4040 if (kwm == KWM_STD) {
4041 curproxy->options &= ~PR_O_HTTP_MODE;
4042 curproxy->options |= PR_O_HTTP_FCL;
4043 goto out;
4044 }
4045 else if (kwm == KWM_NO) {
4046 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4047 curproxy->options &= ~PR_O_HTTP_MODE;
4048 goto out;
4049 }
4050 }
4051 else if (strcmp(args[1], "http-server-close") == 0) {
4052 if (kwm == KWM_STD) {
4053 curproxy->options &= ~PR_O_HTTP_MODE;
4054 curproxy->options |= PR_O_HTTP_SCL;
4055 goto out;
4056 }
4057 else if (kwm == KWM_NO) {
4058 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4059 curproxy->options &= ~PR_O_HTTP_MODE;
4060 goto out;
4061 }
4062 }
4063 else if (strcmp(args[1], "http-keep-alive") == 0) {
4064 if (kwm == KWM_STD) {
4065 curproxy->options &= ~PR_O_HTTP_MODE;
4066 curproxy->options |= PR_O_HTTP_KAL;
4067 goto out;
4068 }
4069 else if (kwm == KWM_NO) {
4070 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4071 curproxy->options &= ~PR_O_HTTP_MODE;
4072 goto out;
4073 }
4074 }
4075 else if (strcmp(args[1], "http-tunnel") == 0) {
4076 if (kwm == KWM_STD) {
4077 curproxy->options &= ~PR_O_HTTP_MODE;
4078 curproxy->options |= PR_O_HTTP_TUN;
4079 goto out;
4080 }
4081 else if (kwm == KWM_NO) {
4082 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4083 curproxy->options &= ~PR_O_HTTP_MODE;
4084 goto out;
4085 }
4086 }
4087
Joseph Lynch726ab712015-05-11 23:25:34 -07004088 /* Redispatch can take an integer argument that control when the
4089 * resispatch occurs. All values are relative to the retries option.
4090 * This can be cancelled using "no option xxx".
4091 */
4092 if (strcmp(args[1], "redispatch") == 0) {
4093 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4094 err_code |= ERR_WARN;
4095 goto out;
4096 }
4097
4098 curproxy->no_options &= ~PR_O_REDISP;
4099 curproxy->options &= ~PR_O_REDISP;
4100
4101 switch (kwm) {
4102 case KWM_STD:
4103 curproxy->options |= PR_O_REDISP;
4104 curproxy->redispatch_after = -1;
4105 if(*args[2]) {
4106 curproxy->redispatch_after = atol(args[2]);
4107 }
4108 break;
4109 case KWM_NO:
4110 curproxy->no_options |= PR_O_REDISP;
4111 curproxy->redispatch_after = 0;
4112 break;
4113 case KWM_DEF: /* already cleared */
4114 break;
4115 }
4116 goto out;
4117 }
4118
Willy Tarreau3842f002009-06-14 11:39:52 +02004119 if (kwm != KWM_STD) {
4120 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004121 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004122 err_code |= ERR_ALERT | ERR_FATAL;
4123 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004124 }
4125
Emeric Brun3a058f32009-06-30 18:26:00 +02004126 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004127 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004128 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004129 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004130 if (*(args[2]) != '\0') {
4131 if (!strcmp(args[2], "clf")) {
4132 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004133 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004134 } else {
4135 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02004136 err_code |= ERR_ALERT | ERR_FATAL;
4137 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004138 }
4139 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004140 if (curproxy->conf.logformat_string != default_http_log_format &&
4141 curproxy->conf.logformat_string != default_tcp_log_format &&
4142 curproxy->conf.logformat_string != clf_http_log_format)
4143 free(curproxy->conf.logformat_string);
4144 curproxy->conf.logformat_string = logformat;
4145
4146 free(curproxy->conf.lfs_file);
4147 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4148 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004149 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004150 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004151 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004152 if (curproxy->conf.logformat_string != default_http_log_format &&
4153 curproxy->conf.logformat_string != default_tcp_log_format &&
4154 curproxy->conf.logformat_string != clf_http_log_format)
4155 free(curproxy->conf.logformat_string);
4156 curproxy->conf.logformat_string = default_tcp_log_format;
4157
4158 free(curproxy->conf.lfs_file);
4159 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4160 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004161 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004162 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004163 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004164 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004165 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004166
4167 if (curproxy->cap & PR_CAP_FE)
4168 curproxy->options |= PR_O_TCP_CLI_KA;
4169 if (curproxy->cap & PR_CAP_BE)
4170 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004171 }
4172 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004173 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004174 err_code |= ERR_WARN;
4175
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004177 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004178 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004179 curproxy->options2 &= ~PR_O2_CHK_ANY;
4180 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004181 if (!*args[2]) { /* no argument */
4182 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4183 curproxy->check_len = strlen(DEF_CHECK_REQ);
4184 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004185 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004186 curproxy->check_req = (char *)malloc(reqlen);
4187 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004188 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004189 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004190 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004191 if (*args[4])
4192 reqlen += strlen(args[4]);
4193 else
4194 reqlen += strlen("HTTP/1.0");
4195
4196 curproxy->check_req = (char *)malloc(reqlen);
4197 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004198 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004199 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004200 }
4201 else if (!strcmp(args[1], "ssl-hello-chk")) {
4202 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004203 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004204 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004205
Willy Tarreaua534fea2008-08-03 12:19:50 +02004206 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004207 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004208 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004209 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004210 }
Willy Tarreau23677902007-05-08 23:50:35 +02004211 else if (!strcmp(args[1], "smtpchk")) {
4212 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004213 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004214 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004215 curproxy->options2 &= ~PR_O2_CHK_ANY;
4216 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004217
4218 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4219 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4220 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4221 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4222 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4223 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4224 curproxy->check_req = (char *)malloc(reqlen);
4225 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4226 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4227 } else {
4228 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4229 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4230 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4231 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4232 }
4233 }
4234 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004235 else if (!strcmp(args[1], "pgsql-check")) {
4236 /* use PostgreSQL request to check servers' health */
4237 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4238 err_code |= ERR_WARN;
4239
4240 free(curproxy->check_req);
4241 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004242 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004243 curproxy->options2 |= PR_O2_PGSQL_CHK;
4244
4245 if (*(args[2])) {
4246 int cur_arg = 2;
4247
4248 while (*(args[cur_arg])) {
4249 if (strcmp(args[cur_arg], "user") == 0) {
4250 char * packet;
4251 uint32_t packet_len;
4252 uint32_t pv;
4253
4254 /* suboption header - needs additional argument for it */
4255 if (*(args[cur_arg+1]) == 0) {
4256 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4257 file, linenum, args[0], args[1], args[cur_arg]);
4258 err_code |= ERR_ALERT | ERR_FATAL;
4259 goto out;
4260 }
4261
4262 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4263 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4264 pv = htonl(0x30000); /* protocol version 3.0 */
4265
4266 packet = (char*) calloc(1, packet_len);
4267
4268 memcpy(packet + 4, &pv, 4);
4269
4270 /* copy "user" */
4271 memcpy(packet + 8, "user", 4);
4272
4273 /* copy username */
4274 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4275
4276 free(curproxy->check_req);
4277 curproxy->check_req = packet;
4278 curproxy->check_len = packet_len;
4279
4280 packet_len = htonl(packet_len);
4281 memcpy(packet, &packet_len, 4);
4282 cur_arg += 2;
4283 } else {
4284 /* unknown suboption - catchall */
4285 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4286 file, linenum, args[0], args[1]);
4287 err_code |= ERR_ALERT | ERR_FATAL;
4288 goto out;
4289 }
4290 } /* end while loop */
4291 }
4292 }
4293
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004294 else if (!strcmp(args[1], "redis-check")) {
4295 /* use REDIS PING request to check servers' health */
4296 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4297 err_code |= ERR_WARN;
4298
4299 free(curproxy->check_req);
4300 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004301 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004302 curproxy->options2 |= PR_O2_REDIS_CHK;
4303
4304 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4305 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4306 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4307 }
4308
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004309 else if (!strcmp(args[1], "mysql-check")) {
4310 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004311 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4312 err_code |= ERR_WARN;
4313
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004314 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004315 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004316 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004317 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004318
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004319 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004320 * const char mysql40_client_auth_pkt[] = {
4321 * "\x0e\x00\x00" // packet length
4322 * "\x01" // packet number
4323 * "\x00\x00" // client capabilities
4324 * "\x00\x00\x01" // max packet
4325 * "haproxy\x00" // username (null terminated string)
4326 * "\x00" // filler (always 0x00)
4327 * "\x01\x00\x00" // packet length
4328 * "\x00" // packet number
4329 * "\x01" // COM_QUIT command
4330 * };
4331 */
4332
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004333 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4334 * const char mysql41_client_auth_pkt[] = {
4335 * "\x0e\x00\x00\" // packet length
4336 * "\x01" // packet number
4337 * "\x00\x00\x00\x00" // client capabilities
4338 * "\x00\x00\x00\x01" // max packet
4339 * "\x21" // character set (UTF-8)
4340 * char[23] // All zeroes
4341 * "haproxy\x00" // username (null terminated string)
4342 * "\x00" // filler (always 0x00)
4343 * "\x01\x00\x00" // packet length
4344 * "\x00" // packet number
4345 * "\x01" // COM_QUIT command
4346 * };
4347 */
4348
4349
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004350 if (*(args[2])) {
4351 int cur_arg = 2;
4352
4353 while (*(args[cur_arg])) {
4354 if (strcmp(args[cur_arg], "user") == 0) {
4355 char *mysqluser;
4356 int packetlen, reqlen, userlen;
4357
4358 /* suboption header - needs additional argument for it */
4359 if (*(args[cur_arg+1]) == 0) {
4360 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4361 file, linenum, args[0], args[1], args[cur_arg]);
4362 err_code |= ERR_ALERT | ERR_FATAL;
4363 goto out;
4364 }
4365 mysqluser = args[cur_arg + 1];
4366 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004367
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004368 if (*(args[cur_arg+2])) {
4369 if (!strcmp(args[cur_arg+2], "post-41")) {
4370 packetlen = userlen + 7 + 27;
4371 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004372
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004373 free(curproxy->check_req);
4374 curproxy->check_req = (char *)calloc(1, reqlen);
4375 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004376
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004377 snprintf(curproxy->check_req, 4, "%c%c%c",
4378 ((unsigned char) packetlen & 0xff),
4379 ((unsigned char) (packetlen >> 8) & 0xff),
4380 ((unsigned char) (packetlen >> 16) & 0xff));
4381
4382 curproxy->check_req[3] = 1;
4383 curproxy->check_req[5] = 130;
4384 curproxy->check_req[11] = 1;
4385 curproxy->check_req[12] = 33;
4386 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4387 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4388 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4389 cur_arg += 3;
4390 } else {
4391 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4392 err_code |= ERR_ALERT | ERR_FATAL;
4393 goto out;
4394 }
4395 } else {
4396 packetlen = userlen + 7;
4397 reqlen = packetlen + 9;
4398
4399 free(curproxy->check_req);
4400 curproxy->check_req = (char *)calloc(1, reqlen);
4401 curproxy->check_len = reqlen;
4402
4403 snprintf(curproxy->check_req, 4, "%c%c%c",
4404 ((unsigned char) packetlen & 0xff),
4405 ((unsigned char) (packetlen >> 8) & 0xff),
4406 ((unsigned char) (packetlen >> 16) & 0xff));
4407
4408 curproxy->check_req[3] = 1;
4409 curproxy->check_req[5] = 128;
4410 curproxy->check_req[8] = 1;
4411 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4412 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4413 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4414 cur_arg += 2;
4415 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004416 } else {
4417 /* unknown suboption - catchall */
4418 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4419 file, linenum, args[0], args[1]);
4420 err_code |= ERR_ALERT | ERR_FATAL;
4421 goto out;
4422 }
4423 } /* end while loop */
4424 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004425 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004426 else if (!strcmp(args[1], "ldap-check")) {
4427 /* use LDAP request to check servers' health */
4428 free(curproxy->check_req);
4429 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004430 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004431 curproxy->options2 |= PR_O2_LDAP_CHK;
4432
4433 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4434 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4435 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4436 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004437 else if (!strcmp(args[1], "tcp-check")) {
4438 /* use raw TCPCHK send/expect to check servers' health */
4439 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4440 err_code |= ERR_WARN;
4441
4442 free(curproxy->check_req);
4443 curproxy->check_req = NULL;
4444 curproxy->options2 &= ~PR_O2_CHK_ANY;
4445 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4446 }
Simon Horman98637e52014-06-20 12:30:16 +09004447 else if (!strcmp(args[1], "external-check")) {
4448 /* excute an external command to check servers' health */
4449 free(curproxy->check_req);
4450 curproxy->check_req = NULL;
4451 curproxy->options2 &= ~PR_O2_CHK_ANY;
4452 curproxy->options2 |= PR_O2_EXT_CHK;
4453 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004454 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004455 int cur_arg;
4456
4457 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4458 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004459 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004460
Willy Tarreau87cf5142011-08-19 22:57:24 +02004461 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004462
4463 free(curproxy->fwdfor_hdr_name);
4464 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4465 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4466
4467 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4468 cur_arg = 2;
4469 while (*(args[cur_arg])) {
4470 if (!strcmp(args[cur_arg], "except")) {
4471 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004472 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004473 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4474 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004475 err_code |= ERR_ALERT | ERR_FATAL;
4476 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004477 }
4478 /* flush useless bits */
4479 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004480 cur_arg += 2;
4481 } else if (!strcmp(args[cur_arg], "header")) {
4482 /* suboption header - needs additional argument for it */
4483 if (*(args[cur_arg+1]) == 0) {
4484 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4485 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004486 err_code |= ERR_ALERT | ERR_FATAL;
4487 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004488 }
4489 free(curproxy->fwdfor_hdr_name);
4490 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4491 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4492 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004493 } else if (!strcmp(args[cur_arg], "if-none")) {
4494 curproxy->options &= ~PR_O_FF_ALWAYS;
4495 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004496 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004497 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004498 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004499 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004500 err_code |= ERR_ALERT | ERR_FATAL;
4501 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004502 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004503 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004504 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004505 else if (!strcmp(args[1], "originalto")) {
4506 int cur_arg;
4507
4508 /* insert x-original-to field, but not for the IP address listed as an except.
4509 * set default options (ie: bitfield, header name, etc)
4510 */
4511
4512 curproxy->options |= PR_O_ORGTO;
4513
4514 free(curproxy->orgto_hdr_name);
4515 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4516 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4517
Willy Tarreau87cf5142011-08-19 22:57:24 +02004518 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004519 cur_arg = 2;
4520 while (*(args[cur_arg])) {
4521 if (!strcmp(args[cur_arg], "except")) {
4522 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004523 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 +02004524 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4525 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004526 err_code |= ERR_ALERT | ERR_FATAL;
4527 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004528 }
4529 /* flush useless bits */
4530 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4531 cur_arg += 2;
4532 } else if (!strcmp(args[cur_arg], "header")) {
4533 /* suboption header - needs additional argument for it */
4534 if (*(args[cur_arg+1]) == 0) {
4535 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4536 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004537 err_code |= ERR_ALERT | ERR_FATAL;
4538 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004539 }
4540 free(curproxy->orgto_hdr_name);
4541 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4542 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4543 cur_arg += 2;
4544 } else {
4545 /* unknown suboption - catchall */
4546 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4547 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004548 err_code |= ERR_ALERT | ERR_FATAL;
4549 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004550 }
4551 } /* end while loop */
4552 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004553 else {
4554 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004555 err_code |= ERR_ALERT | ERR_FATAL;
4556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004557 }
Willy Tarreau93893792009-07-23 13:19:11 +02004558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004559 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004560 else if (!strcmp(args[0], "default_backend")) {
4561 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004562 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004563
4564 if (*(args[1]) == 0) {
4565 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004566 err_code |= ERR_ALERT | ERR_FATAL;
4567 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004568 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004569 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004570 curproxy->defbe.name = strdup(args[1]);
4571 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004572 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004573 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004574 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004575
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004576 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4577 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 +01004578 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004579 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004580 /* enable reconnections to dispatch */
4581 curproxy->options |= PR_O_REDISP;
4582 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004583 else if (!strcmp(args[0], "http-check")) {
4584 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004585 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004586
4587 if (strcmp(args[1], "disable-on-404") == 0) {
4588 /* enable a graceful server shutdown on an HTTP 404 response */
4589 curproxy->options |= PR_O_DISABLE404;
4590 }
Willy Tarreauef781042010-01-27 11:53:01 +01004591 else if (strcmp(args[1], "send-state") == 0) {
4592 /* enable emission of the apparent state of a server in HTTP checks */
4593 curproxy->options2 |= PR_O2_CHK_SNDST;
4594 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004595 else if (strcmp(args[1], "expect") == 0) {
4596 const char *ptr_arg;
4597 int cur_arg;
4598
4599 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4600 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4601 err_code |= ERR_ALERT | ERR_FATAL;
4602 goto out;
4603 }
4604
4605 cur_arg = 2;
4606 /* consider exclamation marks, sole or at the beginning of a word */
4607 while (*(ptr_arg = args[cur_arg])) {
4608 while (*ptr_arg == '!') {
4609 curproxy->options2 ^= PR_O2_EXP_INV;
4610 ptr_arg++;
4611 }
4612 if (*ptr_arg)
4613 break;
4614 cur_arg++;
4615 }
4616 /* now ptr_arg points to the beginning of a word past any possible
4617 * exclamation mark, and cur_arg is the argument which holds this word.
4618 */
4619 if (strcmp(ptr_arg, "status") == 0) {
4620 if (!*(args[cur_arg + 1])) {
4621 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4622 file, linenum, args[0], args[1], ptr_arg);
4623 err_code |= ERR_ALERT | ERR_FATAL;
4624 goto out;
4625 }
4626 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004627 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004628 curproxy->expect_str = strdup(args[cur_arg + 1]);
4629 }
4630 else if (strcmp(ptr_arg, "string") == 0) {
4631 if (!*(args[cur_arg + 1])) {
4632 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4633 file, linenum, args[0], args[1], ptr_arg);
4634 err_code |= ERR_ALERT | ERR_FATAL;
4635 goto out;
4636 }
4637 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004638 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004639 curproxy->expect_str = strdup(args[cur_arg + 1]);
4640 }
4641 else if (strcmp(ptr_arg, "rstatus") == 0) {
4642 if (!*(args[cur_arg + 1])) {
4643 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4644 file, linenum, args[0], args[1], ptr_arg);
4645 err_code |= ERR_ALERT | ERR_FATAL;
4646 goto out;
4647 }
4648 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004649 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004650 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004651 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004652 free(curproxy->expect_regex);
4653 curproxy->expect_regex = NULL;
4654 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004655 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004656 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4657 error = NULL;
4658 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4659 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4660 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4661 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004662 err_code |= ERR_ALERT | ERR_FATAL;
4663 goto out;
4664 }
4665 }
4666 else if (strcmp(ptr_arg, "rstring") == 0) {
4667 if (!*(args[cur_arg + 1])) {
4668 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4669 file, linenum, args[0], args[1], ptr_arg);
4670 err_code |= ERR_ALERT | ERR_FATAL;
4671 goto out;
4672 }
4673 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004674 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004675 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004676 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004677 free(curproxy->expect_regex);
4678 curproxy->expect_regex = NULL;
4679 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004680 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004681 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4682 error = NULL;
4683 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4684 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4685 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4686 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004687 err_code |= ERR_ALERT | ERR_FATAL;
4688 goto out;
4689 }
4690 }
4691 else {
4692 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4693 file, linenum, args[0], args[1], ptr_arg);
4694 err_code |= ERR_ALERT | ERR_FATAL;
4695 goto out;
4696 }
4697 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004698 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004699 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 +02004700 err_code |= ERR_ALERT | ERR_FATAL;
4701 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004702 }
4703 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004704 else if (!strcmp(args[0], "tcp-check")) {
4705 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4706 err_code |= ERR_WARN;
4707
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004708 if (strcmp(args[1], "comment") == 0) {
4709 int cur_arg;
4710 struct tcpcheck_rule *tcpcheck;
4711
4712 cur_arg = 1;
4713 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4714 tcpcheck->action = TCPCHK_ACT_COMMENT;
4715
4716 if (!*args[cur_arg + 1]) {
4717 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4718 file, linenum, args[cur_arg]);
4719 err_code |= ERR_ALERT | ERR_FATAL;
4720 goto out;
4721 }
4722
4723 tcpcheck->comment = strdup(args[cur_arg + 1]);
4724
4725 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4726 }
4727 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004728 const char *ptr_arg;
4729 int cur_arg;
4730 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004731
4732 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02004733 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
4734 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
4735 tcpcheck->action == TCPCHK_ACT_COMMENT) {
4736 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
4737 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004738
Willy Tarreau5581c272015-05-13 12:24:53 +02004739 if (&tcpcheck->list != &curproxy->tcpcheck_rules
4740 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4741 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4742 file, linenum);
4743 err_code |= ERR_ALERT | ERR_FATAL;
4744 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004745 }
4746
4747 cur_arg = 2;
4748 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4749 tcpcheck->action = TCPCHK_ACT_CONNECT;
4750
4751 /* parsing each parameters to fill up the rule */
4752 while (*(ptr_arg = args[cur_arg])) {
4753 /* tcp port */
4754 if (strcmp(args[cur_arg], "port") == 0) {
4755 if ( (atol(args[cur_arg + 1]) > 65535) ||
4756 (atol(args[cur_arg + 1]) < 1) ){
4757 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4758 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4759 err_code |= ERR_ALERT | ERR_FATAL;
4760 goto out;
4761 }
4762 tcpcheck->port = atol(args[cur_arg + 1]);
4763 cur_arg += 2;
4764 }
4765 /* send proxy protocol */
4766 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4767 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4768 cur_arg++;
4769 }
4770#ifdef USE_OPENSSL
4771 else if (strcmp(args[cur_arg], "ssl") == 0) {
4772 curproxy->options |= PR_O_TCPCHK_SSL;
4773 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4774 cur_arg++;
4775 }
4776#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004777 /* comment for this tcpcheck line */
4778 else if (strcmp(args[cur_arg], "comment") == 0) {
4779 if (!*args[cur_arg + 1]) {
4780 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4781 file, linenum, args[cur_arg]);
4782 err_code |= ERR_ALERT | ERR_FATAL;
4783 goto out;
4784 }
4785 tcpcheck->comment = strdup(args[cur_arg + 1]);
4786 cur_arg += 2;
4787 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004788 else {
4789#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004790 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 +01004791#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004792 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 +01004793#endif /* USE_OPENSSL */
4794 file, linenum, args[0], args[1], args[cur_arg]);
4795 err_code |= ERR_ALERT | ERR_FATAL;
4796 goto out;
4797 }
4798
4799 }
4800
4801 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4802 }
4803 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004804 if (! *(args[2]) ) {
4805 /* SEND string expected */
4806 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4807 file, linenum, args[0], args[1], args[2]);
4808 err_code |= ERR_ALERT | ERR_FATAL;
4809 goto out;
4810 } else {
4811 struct tcpcheck_rule *tcpcheck;
4812
4813 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4814
4815 tcpcheck->action = TCPCHK_ACT_SEND;
4816 tcpcheck->string_len = strlen(args[2]);
4817 tcpcheck->string = strdup(args[2]);
4818 tcpcheck->expect_regex = NULL;
4819
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004820 /* comment for this tcpcheck line */
4821 if (strcmp(args[3], "comment") == 0) {
4822 if (!*args[4]) {
4823 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4824 file, linenum, args[3]);
4825 err_code |= ERR_ALERT | ERR_FATAL;
4826 goto out;
4827 }
4828 tcpcheck->comment = strdup(args[4]);
4829 }
4830
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004831 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4832 }
4833 }
4834 else if (strcmp(args[1], "send-binary") == 0) {
4835 if (! *(args[2]) ) {
4836 /* SEND binary string expected */
4837 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4838 file, linenum, args[0], args[1], args[2]);
4839 err_code |= ERR_ALERT | ERR_FATAL;
4840 goto out;
4841 } else {
4842 struct tcpcheck_rule *tcpcheck;
4843 char *err = NULL;
4844
4845 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4846
4847 tcpcheck->action = TCPCHK_ACT_SEND;
4848 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4849 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4850 file, linenum, args[0], args[1], args[2], err);
4851 err_code |= ERR_ALERT | ERR_FATAL;
4852 goto out;
4853 }
4854 tcpcheck->expect_regex = NULL;
4855
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004856 /* comment for this tcpcheck line */
4857 if (strcmp(args[3], "comment") == 0) {
4858 if (!*args[4]) {
4859 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4860 file, linenum, args[3]);
4861 err_code |= ERR_ALERT | ERR_FATAL;
4862 goto out;
4863 }
4864 tcpcheck->comment = strdup(args[4]);
4865 }
4866
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004867 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4868 }
4869 }
4870 else if (strcmp(args[1], "expect") == 0) {
4871 const char *ptr_arg;
4872 int cur_arg;
4873 int inverse = 0;
4874
4875 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4876 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4877 err_code |= ERR_ALERT | ERR_FATAL;
4878 goto out;
4879 }
4880
4881 cur_arg = 2;
4882 /* consider exclamation marks, sole or at the beginning of a word */
4883 while (*(ptr_arg = args[cur_arg])) {
4884 while (*ptr_arg == '!') {
4885 inverse = !inverse;
4886 ptr_arg++;
4887 }
4888 if (*ptr_arg)
4889 break;
4890 cur_arg++;
4891 }
4892 /* now ptr_arg points to the beginning of a word past any possible
4893 * exclamation mark, and cur_arg is the argument which holds this word.
4894 */
4895 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004896 struct tcpcheck_rule *tcpcheck;
4897 char *err = NULL;
4898
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004899 if (!*(args[cur_arg + 1])) {
4900 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4901 file, linenum, args[0], args[1], ptr_arg);
4902 err_code |= ERR_ALERT | ERR_FATAL;
4903 goto out;
4904 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004905
4906 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4907
4908 tcpcheck->action = TCPCHK_ACT_EXPECT;
4909 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4910 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4911 file, linenum, args[0], args[1], args[2], err);
4912 err_code |= ERR_ALERT | ERR_FATAL;
4913 goto out;
4914 }
4915 tcpcheck->expect_regex = NULL;
4916 tcpcheck->inverse = inverse;
4917
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004918 /* tcpcheck comment */
4919 cur_arg += 2;
4920 if (strcmp(args[cur_arg], "comment") == 0) {
4921 if (!*args[cur_arg + 1]) {
4922 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4923 file, linenum, args[cur_arg + 1]);
4924 err_code |= ERR_ALERT | ERR_FATAL;
4925 goto out;
4926 }
4927 tcpcheck->comment = strdup(args[cur_arg + 1]);
4928 }
4929
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004930 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4931 }
4932 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004933 struct tcpcheck_rule *tcpcheck;
4934
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004935 if (!*(args[cur_arg + 1])) {
4936 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4937 file, linenum, args[0], args[1], ptr_arg);
4938 err_code |= ERR_ALERT | ERR_FATAL;
4939 goto out;
4940 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004941
4942 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4943
4944 tcpcheck->action = TCPCHK_ACT_EXPECT;
4945 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4946 tcpcheck->string = strdup(args[cur_arg + 1]);
4947 tcpcheck->expect_regex = NULL;
4948 tcpcheck->inverse = inverse;
4949
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004950 /* tcpcheck comment */
4951 cur_arg += 2;
4952 if (strcmp(args[cur_arg], "comment") == 0) {
4953 if (!*args[cur_arg + 1]) {
4954 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4955 file, linenum, args[cur_arg + 1]);
4956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
4958 }
4959 tcpcheck->comment = strdup(args[cur_arg + 1]);
4960 }
4961
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004962 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4963 }
4964 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004965 struct tcpcheck_rule *tcpcheck;
4966
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004967 if (!*(args[cur_arg + 1])) {
4968 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4969 file, linenum, args[0], args[1], ptr_arg);
4970 err_code |= ERR_ALERT | ERR_FATAL;
4971 goto out;
4972 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004973
4974 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4975
4976 tcpcheck->action = TCPCHK_ACT_EXPECT;
4977 tcpcheck->string_len = 0;
4978 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004979 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4980 error = NULL;
4981 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4982 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4983 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4984 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004985 err_code |= ERR_ALERT | ERR_FATAL;
4986 goto out;
4987 }
4988 tcpcheck->inverse = inverse;
4989
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004990 /* tcpcheck comment */
4991 cur_arg += 2;
4992 if (strcmp(args[cur_arg], "comment") == 0) {
4993 if (!*args[cur_arg + 1]) {
4994 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4995 file, linenum, args[cur_arg + 1]);
4996 err_code |= ERR_ALERT | ERR_FATAL;
4997 goto out;
4998 }
4999 tcpcheck->comment = strdup(args[cur_arg + 1]);
5000 }
5001
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005002 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5003 }
5004 else {
5005 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5006 file, linenum, args[0], args[1], ptr_arg);
5007 err_code |= ERR_ALERT | ERR_FATAL;
5008 goto out;
5009 }
5010 }
5011 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005012 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005013 err_code |= ERR_ALERT | ERR_FATAL;
5014 goto out;
5015 }
5016 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005017 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005018 if (curproxy == &defproxy) {
5019 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005020 err_code |= ERR_ALERT | ERR_FATAL;
5021 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005022 }
5023
Willy Tarreaub80c2302007-11-30 20:51:32 +01005024 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005025 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005026
5027 if (strcmp(args[1], "fail") == 0) {
5028 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005029 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005030 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5031 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005032 err_code |= ERR_ALERT | ERR_FATAL;
5033 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005034 }
5035
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005036 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5037 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5038 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005039 err_code |= ERR_ALERT | ERR_FATAL;
5040 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005041 }
5042 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5043 }
5044 else {
5045 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005046 err_code |= ERR_ALERT | ERR_FATAL;
5047 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005048 }
5049 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005050#ifdef TPROXY
5051 else if (!strcmp(args[0], "transparent")) {
5052 /* enable transparent proxy connections */
5053 curproxy->options |= PR_O_TRANSP;
5054 }
5055#endif
5056 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005057 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005058 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005059
Willy Tarreaubaaee002006-06-26 02:48:02 +02005060 if (*(args[1]) == 0) {
5061 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005062 err_code |= ERR_ALERT | ERR_FATAL;
5063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005064 }
5065 curproxy->maxconn = atol(args[1]);
5066 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005067 else if (!strcmp(args[0], "backlog")) { /* backlog */
5068 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005069 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005070
5071 if (*(args[1]) == 0) {
5072 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005073 err_code |= ERR_ALERT | ERR_FATAL;
5074 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005075 }
5076 curproxy->backlog = atol(args[1]);
5077 }
Willy Tarreau86034312006-12-29 00:10:33 +01005078 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005079 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005080 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005081
Willy Tarreau86034312006-12-29 00:10:33 +01005082 if (*(args[1]) == 0) {
5083 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005084 err_code |= ERR_ALERT | ERR_FATAL;
5085 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005086 }
5087 curproxy->fullconn = atol(args[1]);
5088 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5090 if (*(args[1]) == 0) {
5091 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005092 err_code |= ERR_ALERT | ERR_FATAL;
5093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005094 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005095 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5096 if (err) {
5097 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5098 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005101 }
5102 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005103 }
5104 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005105 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005106 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005107 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005108
Willy Tarreaubaaee002006-06-26 02:48:02 +02005109 if (curproxy == &defproxy) {
5110 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005111 err_code |= ERR_ALERT | ERR_FATAL;
5112 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005113 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005114 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005115 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005116
Willy Tarreau902636f2013-03-10 19:44:48 +01005117 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005118 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005119 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005120 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005121 goto out;
5122 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005123
5124 proto = protocol_by_family(sk->ss_family);
5125 if (!proto || !proto->connect) {
5126 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5127 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005128 err_code |= ERR_ALERT | ERR_FATAL;
5129 goto out;
5130 }
5131
5132 if (port1 != port2) {
5133 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5134 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005135 err_code |= ERR_ALERT | ERR_FATAL;
5136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005137 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005138
5139 if (!port1) {
5140 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5141 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005142 err_code |= ERR_ALERT | ERR_FATAL;
5143 goto out;
5144 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005145
Willy Tarreaud5191e72010-02-09 20:50:45 +01005146 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005147 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005148 }
5149 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005150 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005151 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005152
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005153 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5154 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005155 err_code |= ERR_ALERT | ERR_FATAL;
5156 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005157 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005158 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005159 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005160 /**
5161 * The syntax for hash-type config element is
5162 * hash-type {map-based|consistent} [[<algo>] avalanche]
5163 *
5164 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5165 */
5166 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005167
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005168 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5169 err_code |= ERR_WARN;
5170
5171 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005172 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5173 }
5174 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005175 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5176 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005177 else if (strcmp(args[1], "avalanche") == 0) {
5178 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]);
5179 err_code |= ERR_ALERT | ERR_FATAL;
5180 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005181 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005182 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005183 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005184 err_code |= ERR_ALERT | ERR_FATAL;
5185 goto out;
5186 }
Bhaskar98634f02013-10-29 23:30:51 -04005187
5188 /* set the hash function to use */
5189 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005190 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005191 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005192
5193 /* if consistent with no argument, then avalanche modifier is also applied */
5194 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5195 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005196 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005197 /* set the hash function */
5198 if (!strcmp(args[2], "sdbm")) {
5199 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5200 }
5201 else if (!strcmp(args[2], "djb2")) {
5202 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005203 }
5204 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005205 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005206 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005207 else if (!strcmp(args[2], "crc32")) {
5208 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5209 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005210 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005211 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 -05005212 err_code |= ERR_ALERT | ERR_FATAL;
5213 goto out;
5214 }
5215
5216 /* set the hash modifier */
5217 if (!strcmp(args[3], "avalanche")) {
5218 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5219 }
5220 else if (*args[3]) {
5221 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5222 err_code |= ERR_ALERT | ERR_FATAL;
5223 goto out;
5224 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005225 }
William Lallemanda73203e2012-03-12 12:48:57 +01005226 }
William Lallemanda73203e2012-03-12 12:48:57 +01005227 else if (strcmp(args[0], "unique-id-format") == 0) {
5228 if (!*(args[1])) {
5229 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5230 err_code |= ERR_ALERT | ERR_FATAL;
5231 goto out;
5232 }
William Lallemand3203ff42012-11-11 17:30:56 +01005233 if (*(args[2])) {
5234 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5235 err_code |= ERR_ALERT | ERR_FATAL;
5236 goto out;
5237 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005238 free(curproxy->conf.uniqueid_format_string);
5239 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005240
Willy Tarreau62a61232013-04-12 18:13:46 +02005241 free(curproxy->conf.uif_file);
5242 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5243 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005244 }
William Lallemanda73203e2012-03-12 12:48:57 +01005245
5246 else if (strcmp(args[0], "unique-id-header") == 0) {
5247 if (!*(args[1])) {
5248 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5249 err_code |= ERR_ALERT | ERR_FATAL;
5250 goto out;
5251 }
5252 free(curproxy->header_unique_id);
5253 curproxy->header_unique_id = strdup(args[1]);
5254 }
5255
William Lallemand723b73a2012-02-08 16:37:49 +01005256 else if (strcmp(args[0], "log-format") == 0) {
5257 if (!*(args[1])) {
5258 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5259 err_code |= ERR_ALERT | ERR_FATAL;
5260 goto out;
5261 }
William Lallemand3203ff42012-11-11 17:30:56 +01005262 if (*(args[2])) {
5263 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5264 err_code |= ERR_ALERT | ERR_FATAL;
5265 goto out;
5266 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005267
Willy Tarreau62a61232013-04-12 18:13:46 +02005268 if (curproxy->conf.logformat_string != default_http_log_format &&
5269 curproxy->conf.logformat_string != default_tcp_log_format &&
5270 curproxy->conf.logformat_string != clf_http_log_format)
5271 free(curproxy->conf.logformat_string);
5272 curproxy->conf.logformat_string = strdup(args[1]);
5273
5274 free(curproxy->conf.lfs_file);
5275 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5276 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005277
5278 /* get a chance to improve log-format error reporting by
5279 * reporting the correct line-number when possible.
5280 */
5281 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5282 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5283 file, linenum, curproxy->id);
5284 err_code |= ERR_WARN;
5285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005286 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005287 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5288 if (*(args[1]) == 0) {
5289 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5290 err_code |= ERR_ALERT | ERR_FATAL;
5291 goto out;
5292 }
5293 free(curproxy->log_tag);
5294 curproxy->log_tag = strdup(args[1]);
5295 }
William Lallemand0f99e342011-10-12 17:50:54 +02005296 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5297 /* delete previous herited or defined syslog servers */
5298 struct logsrv *back;
5299
5300 if (*(args[1]) != 0) {
5301 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5302 err_code |= ERR_ALERT | ERR_FATAL;
5303 goto out;
5304 }
5305
William Lallemand723b73a2012-02-08 16:37:49 +01005306 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5307 LIST_DEL(&tmplogsrv->list);
5308 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005309 }
5310 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005311 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005312 struct logsrv *logsrv;
5313
Willy Tarreaubaaee002006-06-26 02:48:02 +02005314 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005315 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005316 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005317 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005318 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005319 LIST_INIT(&node->list);
5320 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5321 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005322 }
5323 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005324 struct sockaddr_storage *sk;
5325 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005326 int arg = 0;
5327 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005328
5329 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005330
Willy Tarreau18324f52014-06-27 18:10:07 +02005331 /* just after the address, a length may be specified */
5332 if (strcmp(args[arg+2], "len") == 0) {
5333 len = atoi(args[arg+3]);
5334 if (len < 80 || len > 65535) {
5335 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5336 file, linenum, args[arg+3]);
5337 err_code |= ERR_ALERT | ERR_FATAL;
5338 goto out;
5339 }
5340 logsrv->maxlen = len;
5341
5342 /* skip these two args */
5343 arg += 2;
5344 }
5345 else
5346 logsrv->maxlen = MAX_SYSLOG_LEN;
5347
5348 if (logsrv->maxlen > global.max_syslog_len) {
5349 global.max_syslog_len = logsrv->maxlen;
5350 logline = realloc(logline, global.max_syslog_len + 1);
5351 }
5352
5353 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005354 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005355 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005356 err_code |= ERR_ALERT | ERR_FATAL;
5357 goto out;
5358
Willy Tarreaubaaee002006-06-26 02:48:02 +02005359 }
5360
William Lallemand0f99e342011-10-12 17:50:54 +02005361 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005362 if (*(args[arg+3])) {
5363 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005364 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005365 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005366 err_code |= ERR_ALERT | ERR_FATAL;
5367 goto out;
5368
Willy Tarreaubaaee002006-06-26 02:48:02 +02005369 }
5370 }
5371
William Lallemand0f99e342011-10-12 17:50:54 +02005372 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005373 if (*(args[arg+4])) {
5374 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005375 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005376 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005377 err_code |= ERR_ALERT | ERR_FATAL;
5378 goto out;
5379
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005380 }
5381 }
5382
Willy Tarreau902636f2013-03-10 19:44:48 +01005383 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005384 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005385 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005386 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005387 goto out;
5388 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005389
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005390 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005391
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005392 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005393 if (port1 != port2) {
5394 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5395 file, linenum, args[0], args[1]);
5396 err_code |= ERR_ALERT | ERR_FATAL;
5397 goto out;
5398 }
5399
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005400 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005401 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005402 }
William Lallemand0f99e342011-10-12 17:50:54 +02005403
5404 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005405 }
5406 else {
5407 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5408 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005409 err_code |= ERR_ALERT | ERR_FATAL;
5410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005411 }
5412 }
5413 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005414 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005415 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005416 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005417 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005418
Willy Tarreau977b8e42006-12-29 14:19:17 +01005419 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005420 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005421
Willy Tarreaubaaee002006-06-26 02:48:02 +02005422 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005423 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5424 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005425 err_code |= ERR_ALERT | ERR_FATAL;
5426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005427 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005428
5429 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005430 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5431 free(curproxy->conn_src.iface_name);
5432 curproxy->conn_src.iface_name = NULL;
5433 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005434
Willy Tarreau902636f2013-03-10 19:44:48 +01005435 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005436 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005437 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005438 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005439 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005440 goto out;
5441 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005442
5443 proto = protocol_by_family(sk->ss_family);
5444 if (!proto || !proto->connect) {
5445 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005446 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005447 err_code |= ERR_ALERT | ERR_FATAL;
5448 goto out;
5449 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005450
5451 if (port1 != port2) {
5452 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5453 file, linenum, args[0], args[1]);
5454 err_code |= ERR_ALERT | ERR_FATAL;
5455 goto out;
5456 }
5457
Willy Tarreauef9a3602012-12-08 22:29:20 +01005458 curproxy->conn_src.source_addr = *sk;
5459 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005460
5461 cur_arg = 2;
5462 while (*(args[cur_arg])) {
5463 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005464#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5465#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005466 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005467 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5468 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005469 err_code |= ERR_ALERT | ERR_FATAL;
5470 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005471 }
5472#endif
5473 if (!*args[cur_arg + 1]) {
5474 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5475 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005476 err_code |= ERR_ALERT | ERR_FATAL;
5477 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005478 }
5479
5480 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005481 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5482 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005483 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005484 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5485 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005486 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5487 char *name, *end;
5488
5489 name = args[cur_arg+1] + 7;
5490 while (isspace(*name))
5491 name++;
5492
5493 end = name;
5494 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5495 end++;
5496
Willy Tarreauef9a3602012-12-08 22:29:20 +01005497 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5498 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5499 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5500 curproxy->conn_src.bind_hdr_len = end - name;
5501 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5502 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5503 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005504
5505 /* now look for an occurrence number */
5506 while (isspace(*end))
5507 end++;
5508 if (*end == ',') {
5509 end++;
5510 name = end;
5511 if (*end == '-')
5512 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005513 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005514 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005515 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005516 }
5517
Willy Tarreauef9a3602012-12-08 22:29:20 +01005518 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005519 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5520 " occurrences values smaller than %d.\n",
5521 file, linenum, MAX_HDR_HISTORY);
5522 err_code |= ERR_ALERT | ERR_FATAL;
5523 goto out;
5524 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005525 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005526 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005527
Willy Tarreau902636f2013-03-10 19:44:48 +01005528 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005529 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005530 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005531 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005532 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005533 goto out;
5534 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005535
5536 proto = protocol_by_family(sk->ss_family);
5537 if (!proto || !proto->connect) {
5538 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5539 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005540 err_code |= ERR_ALERT | ERR_FATAL;
5541 goto out;
5542 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005543
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005544 if (port1 != port2) {
5545 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5546 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005547 err_code |= ERR_ALERT | ERR_FATAL;
5548 goto out;
5549 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005550 curproxy->conn_src.tproxy_addr = *sk;
5551 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005552 }
5553 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005554#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005555 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005556#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005557#else /* no TPROXY support */
5558 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005559 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005560 err_code |= ERR_ALERT | ERR_FATAL;
5561 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005562#endif
5563 cur_arg += 2;
5564 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005565 }
5566
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005567 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5568#ifdef SO_BINDTODEVICE
5569 if (!*args[cur_arg + 1]) {
5570 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5571 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005572 err_code |= ERR_ALERT | ERR_FATAL;
5573 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005574 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005575 free(curproxy->conn_src.iface_name);
5576 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5577 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005578 global.last_checks |= LSTCHK_NETADM;
5579#else
5580 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5581 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005582 err_code |= ERR_ALERT | ERR_FATAL;
5583 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005584#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005585 cur_arg += 2;
5586 continue;
5587 }
5588 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005589 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005590 err_code |= ERR_ALERT | ERR_FATAL;
5591 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005592 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005593 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005594 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5595 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5596 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005597 err_code |= ERR_ALERT | ERR_FATAL;
5598 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005599 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005600 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005601 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005602 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5603 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005604 err_code |= ERR_ALERT | ERR_FATAL;
5605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005606 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005607
5608 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005609 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005610 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005611 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005613 }
5614 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005615 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005616 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005617 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005618 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005620 }
5621 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005622 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005623 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005624 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005625 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005626 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005627 }
5628 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005629 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005630 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005631 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005632 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005634 }
5635 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005636 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005637 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005638 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005639 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005641 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005642 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005643 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005644 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005645 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005646 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005647 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005648 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005649 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005650 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005651 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5652 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005653 err_code |= ERR_ALERT | ERR_FATAL;
5654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005655 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005656
5657 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005658 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005659 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005660 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005662 }
5663 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005664 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005665 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005666 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005667 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005669 }
5670 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005671 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005672 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005673 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005674 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005676 }
5677 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005678 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005679 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005680 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005681 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005683 }
5684 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005685 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005686 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005687 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005688 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005690 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005691 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005692 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005693 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005694 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005695 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005696 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005698 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005699 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005700
Willy Tarreaubaaee002006-06-26 02:48:02 +02005701 if (curproxy == &defproxy) {
5702 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005703 err_code |= ERR_ALERT | ERR_FATAL;
5704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005706 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005707 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005708
Willy Tarreaubaaee002006-06-26 02:48:02 +02005709 if (*(args[1]) == 0) {
5710 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005711 err_code |= ERR_ALERT | ERR_FATAL;
5712 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005713 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005714
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005715 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005716 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5717 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5718 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005719 err_code |= ERR_ALERT | ERR_FATAL;
5720 goto out;
5721 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005722 err_code |= warnif_cond_conflicts(cond,
5723 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5724 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005725 }
5726 else if (*args[2]) {
5727 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5728 file, linenum, args[0], args[2]);
5729 err_code |= ERR_ALERT | ERR_FATAL;
5730 goto out;
5731 }
5732
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005733 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005734 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005735 wl->s = strdup(args[1]);
5736 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005737 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738 }
5739 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005740 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005741 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5742 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005743 err_code |= ERR_ALERT | ERR_FATAL;
5744 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005745 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005746
Willy Tarreauade5ec42010-01-28 19:33:49 +01005747 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005748 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005749 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005750 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005752 }
5753 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005754 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005755 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005756 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005757 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005758 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005759 }
5760 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005761 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005762 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005763 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005764 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005765 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005766 }
5767 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005768 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005769 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5770 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005771 err_code |= ERR_ALERT | ERR_FATAL;
5772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005773 }
5774
Willy Tarreauade5ec42010-01-28 19:33:49 +01005775 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005776 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005777 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005778 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005780 }
5781 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005782 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005783 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005784 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005785 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005787 }
5788 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005789 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005790 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005791 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005792 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005794 }
5795 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005796 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005797
Willy Tarreaubaaee002006-06-26 02:48:02 +02005798 if (curproxy == &defproxy) {
5799 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005800 err_code |= ERR_ALERT | ERR_FATAL;
5801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005802 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005803 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005804 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005805
Willy Tarreaubaaee002006-06-26 02:48:02 +02005806 if (*(args[1]) == 0) {
5807 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005808 err_code |= ERR_ALERT | ERR_FATAL;
5809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005810 }
5811
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005812 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005813 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5814 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5815 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005816 err_code |= ERR_ALERT | ERR_FATAL;
5817 goto out;
5818 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005819 err_code |= warnif_cond_conflicts(cond,
5820 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5821 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005822 }
5823 else if (*args[2]) {
5824 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5825 file, linenum, args[0], args[2]);
5826 err_code |= ERR_ALERT | ERR_FATAL;
5827 goto out;
5828 }
5829
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005830 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005831 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005832 wl->s = strdup(args[1]);
5833 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005834 }
5835 else if (!strcmp(args[0], "errorloc") ||
5836 !strcmp(args[0], "errorloc302") ||
5837 !strcmp(args[0], "errorloc303")) { /* error location */
5838 int errnum, errlen;
5839 char *err;
5840
Willy Tarreau977b8e42006-12-29 14:19:17 +01005841 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005842 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005843
Willy Tarreaubaaee002006-06-26 02:48:02 +02005844 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005845 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005846 err_code |= ERR_ALERT | ERR_FATAL;
5847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005848 }
5849
5850 errnum = atol(args[1]);
5851 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005852 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5853 err = malloc(errlen);
5854 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005855 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005856 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5857 err = malloc(errlen);
5858 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005859 }
5860
Willy Tarreau0f772532006-12-23 20:51:41 +01005861 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5862 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005863 chunk_destroy(&curproxy->errmsg[rc]);
5864 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005865 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005866 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005867 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005868
5869 if (rc >= HTTP_ERR_SIZE) {
5870 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5871 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005872 free(err);
5873 }
5874 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005875 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5876 int errnum, errlen, fd;
5877 char *err;
5878 struct stat stat;
5879
5880 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005881 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005882
5883 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005884 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005885 err_code |= ERR_ALERT | ERR_FATAL;
5886 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005887 }
5888
5889 fd = open(args[2], O_RDONLY);
5890 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5891 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5892 file, linenum, args[2], args[1]);
5893 if (fd >= 0)
5894 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005895 err_code |= ERR_ALERT | ERR_FATAL;
5896 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005897 }
5898
Willy Tarreau27a674e2009-08-17 07:23:33 +02005899 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005900 errlen = stat.st_size;
5901 } else {
5902 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005903 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005904 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005905 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005906 }
5907
5908 err = malloc(errlen); /* malloc() must succeed during parsing */
5909 errnum = read(fd, err, errlen);
5910 if (errnum != errlen) {
5911 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5912 file, linenum, args[2], args[1]);
5913 close(fd);
5914 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005915 err_code |= ERR_ALERT | ERR_FATAL;
5916 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005917 }
5918 close(fd);
5919
5920 errnum = atol(args[1]);
5921 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5922 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005923 chunk_destroy(&curproxy->errmsg[rc]);
5924 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005925 break;
5926 }
5927 }
5928
5929 if (rc >= HTTP_ERR_SIZE) {
5930 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5931 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005932 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005933 free(err);
5934 }
5935 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005936 else if (!strcmp(args[0], "compression")) {
5937 struct comp *comp;
5938 if (curproxy->comp == NULL) {
5939 comp = calloc(1, sizeof(struct comp));
5940 curproxy->comp = comp;
5941 } else {
5942 comp = curproxy->comp;
5943 }
5944
5945 if (!strcmp(args[1], "algo")) {
5946 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005947 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005948
William Lallemand82fe75c2012-10-23 10:25:10 +02005949 cur_arg = 2;
5950 if (!*args[cur_arg]) {
5951 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5952 file, linenum, args[0]);
5953 err_code |= ERR_ALERT | ERR_FATAL;
5954 goto out;
5955 }
5956 while (*(args[cur_arg])) {
5957 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5958 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5959 file, linenum, args[0], args[cur_arg]);
5960 err_code |= ERR_ALERT | ERR_FATAL;
5961 goto out;
5962 }
William Lallemand552df672012-11-07 13:21:47 +01005963 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5964 curproxy->comp->algos->end(&ctx);
5965 } else {
5966 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5967 file, linenum, args[0], args[cur_arg]);
5968 err_code |= ERR_ALERT | ERR_FATAL;
5969 goto out;
5970 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005971 cur_arg ++;
5972 continue;
5973 }
5974 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005975 else if (!strcmp(args[1], "offload")) {
5976 comp->offload = 1;
5977 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005978 else if (!strcmp(args[1], "type")) {
5979 int cur_arg;
5980 cur_arg = 2;
5981 if (!*args[cur_arg]) {
5982 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5983 file, linenum, args[0]);
5984 err_code |= ERR_ALERT | ERR_FATAL;
5985 goto out;
5986 }
5987 while (*(args[cur_arg])) {
5988 comp_append_type(comp, args[cur_arg]);
5989 cur_arg ++;
5990 continue;
5991 }
5992 }
5993 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005994 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005995 file, linenum, args[0]);
5996 err_code |= ERR_ALERT | ERR_FATAL;
5997 goto out;
5998 }
5999 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006000 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006001 struct cfg_kw_list *kwl;
6002 int index;
6003
6004 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6005 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6006 if (kwl->kw[index].section != CFG_LISTEN)
6007 continue;
6008 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6009 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006010 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006011 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006012 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006013 err_code |= ERR_ALERT | ERR_FATAL;
6014 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006015 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006016 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006017 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006018 err_code |= ERR_WARN;
6019 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006020 }
Willy Tarreau93893792009-07-23 13:19:11 +02006021 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006022 }
6023 }
6024 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006025
Willy Tarreau6daf3432008-01-22 16:44:08 +01006026 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006027 err_code |= ERR_ALERT | ERR_FATAL;
6028 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006029 }
Willy Tarreau93893792009-07-23 13:19:11 +02006030 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006031 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006032 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006033}
6034
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006035int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006036cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6037{
6038#ifdef CONFIG_HAP_NS
6039 const char *err;
6040 const char *item = args[0];
6041
6042 if (!strcmp(item, "namespace_list")) {
6043 return 0;
6044 }
6045 else if (!strcmp(item, "namespace")) {
6046 size_t idx = 1;
6047 const char *current;
6048 while (*(current = args[idx++])) {
6049 err = invalid_char(current);
6050 if (err) {
6051 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6052 file, linenum, *err, item, current);
6053 return ERR_ALERT | ERR_FATAL;
6054 }
6055
6056 if (netns_store_lookup(current, strlen(current))) {
6057 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6058 file, linenum, current);
6059 return ERR_ALERT | ERR_FATAL;
6060 }
6061 if (!netns_store_insert(current)) {
6062 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6063 file, linenum, current);
6064 return ERR_ALERT | ERR_FATAL;
6065 }
6066 }
6067 }
6068
6069 return 0;
6070#else
6071 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6072 file, linenum);
6073 return ERR_ALERT | ERR_FATAL;
6074#endif
6075}
6076
6077int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006078cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6079{
6080
6081 int err_code = 0;
6082 const char *err;
6083
6084 if (!strcmp(args[0], "userlist")) { /* new userlist */
6085 struct userlist *newul;
6086
6087 if (!*args[1]) {
6088 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6089 file, linenum, args[0]);
6090 err_code |= ERR_ALERT | ERR_FATAL;
6091 goto out;
6092 }
6093
6094 err = invalid_char(args[1]);
6095 if (err) {
6096 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6097 file, linenum, *err, args[0], args[1]);
6098 err_code |= ERR_ALERT | ERR_FATAL;
6099 goto out;
6100 }
6101
6102 for (newul = userlist; newul; newul = newul->next)
6103 if (!strcmp(newul->name, args[1])) {
6104 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6105 file, linenum, args[1]);
6106 err_code |= ERR_WARN;
6107 goto out;
6108 }
6109
6110 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6111 if (!newul) {
6112 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6113 err_code |= ERR_ALERT | ERR_ABORT;
6114 goto out;
6115 }
6116
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006117 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006118 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006119 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6120 err_code |= ERR_ALERT | ERR_ABORT;
6121 goto out;
6122 }
6123
6124 newul->next = userlist;
6125 userlist = newul;
6126
6127 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006128 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006129 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006130 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006131
6132 if (!*args[1]) {
6133 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6134 file, linenum, args[0]);
6135 err_code |= ERR_ALERT | ERR_FATAL;
6136 goto out;
6137 }
6138
6139 err = invalid_char(args[1]);
6140 if (err) {
6141 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6142 file, linenum, *err, args[0], args[1]);
6143 err_code |= ERR_ALERT | ERR_FATAL;
6144 goto out;
6145 }
6146
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006147 for (ag = userlist->groups; ag; ag = ag->next)
6148 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006149 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6150 file, linenum, args[1], userlist->name);
6151 err_code |= ERR_ALERT;
6152 goto out;
6153 }
6154
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006155 ag = calloc(1, sizeof(*ag));
6156 if (!ag) {
6157 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6158 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006159 goto out;
6160 }
6161
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006162 ag->name = strdup(args[1]);
6163 if (!ag) {
6164 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6165 err_code |= ERR_ALERT | ERR_ABORT;
6166 goto out;
6167 }
6168
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006169 cur_arg = 2;
6170
6171 while (*args[cur_arg]) {
6172 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006173 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006174 cur_arg += 2;
6175 continue;
6176 } else {
6177 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6178 file, linenum, args[0]);
6179 err_code |= ERR_ALERT | ERR_FATAL;
6180 goto out;
6181 }
6182 }
6183
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006184 ag->next = userlist->groups;
6185 userlist->groups = ag;
6186
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006187 } else if (!strcmp(args[0], "user")) { /* new user */
6188 struct auth_users *newuser;
6189 int cur_arg;
6190
6191 if (!*args[1]) {
6192 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6193 file, linenum, args[0]);
6194 err_code |= ERR_ALERT | ERR_FATAL;
6195 goto out;
6196 }
6197
6198 for (newuser = userlist->users; newuser; newuser = newuser->next)
6199 if (!strcmp(newuser->user, args[1])) {
6200 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6201 file, linenum, args[1], userlist->name);
6202 err_code |= ERR_ALERT;
6203 goto out;
6204 }
6205
6206 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6207 if (!newuser) {
6208 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6209 err_code |= ERR_ALERT | ERR_ABORT;
6210 goto out;
6211 }
6212
6213 newuser->user = strdup(args[1]);
6214
6215 newuser->next = userlist->users;
6216 userlist->users = newuser;
6217
6218 cur_arg = 2;
6219
6220 while (*args[cur_arg]) {
6221 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006222#ifdef CONFIG_HAP_CRYPT
6223 if (!crypt("", args[cur_arg + 1])) {
6224 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6225 file, linenum, newuser->user);
6226 err_code |= ERR_ALERT | ERR_FATAL;
6227 goto out;
6228 }
6229#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006230 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6231 file, linenum);
6232 err_code |= ERR_ALERT;
6233#endif
6234 newuser->pass = strdup(args[cur_arg + 1]);
6235 cur_arg += 2;
6236 continue;
6237 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6238 newuser->pass = strdup(args[cur_arg + 1]);
6239 newuser->flags |= AU_O_INSECURE;
6240 cur_arg += 2;
6241 continue;
6242 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006243 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006244 cur_arg += 2;
6245 continue;
6246 } else {
6247 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6248 file, linenum, args[0]);
6249 err_code |= ERR_ALERT | ERR_FATAL;
6250 goto out;
6251 }
6252 }
6253 } else {
6254 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6255 err_code |= ERR_ALERT | ERR_FATAL;
6256 }
6257
6258out:
6259 return err_code;
6260}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006261
6262/*
6263 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006264 * Returns the error code, 0 if OK, or any combination of :
6265 * - ERR_ABORT: must abort ASAP
6266 * - ERR_FATAL: we can continue parsing but not start the service
6267 * - ERR_WARN: a warning has been emitted
6268 * - ERR_ALERT: an alert has been emitted
6269 * Only the two first ones can stop processing, the two others are just
6270 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006271 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006272int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006273{
William Lallemand64e84512015-05-12 14:25:37 +02006274 char *thisline;
6275 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006276 FILE *f;
6277 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006278 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006279 struct cfg_section *cs = NULL;
6280 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006281 int readbytes = 0;
6282
6283 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006284 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006285 return -1;
6286 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006287
6288 /* Register internal sections */
6289 if (!cfg_register_section("listen", cfg_parse_listen) ||
6290 !cfg_register_section("frontend", cfg_parse_listen) ||
6291 !cfg_register_section("backend", cfg_parse_listen) ||
6292 !cfg_register_section("ruleset", cfg_parse_listen) ||
6293 !cfg_register_section("defaults", cfg_parse_listen) ||
6294 !cfg_register_section("global", cfg_parse_global) ||
6295 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006296 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006297 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006298 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006299 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006300
Willy Tarreaubaaee002006-06-26 02:48:02 +02006301 if ((f=fopen(file,"r")) == NULL)
6302 return -1;
6303
William Lallemandb2f07452015-05-12 14:27:13 +02006304next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006305 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006306 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006307 char *end;
6308 char *args[MAX_LINE_ARGS + 1];
6309 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006310 int dquote = 0; /* double quote */
6311 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006312
Willy Tarreaubaaee002006-06-26 02:48:02 +02006313 linenum++;
6314
6315 end = line + strlen(line);
6316
William Lallemand64e84512015-05-12 14:25:37 +02006317 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006318 /* Check if we reached the limit and the last char is not \n.
6319 * Watch out for the last line without the terminating '\n'!
6320 */
William Lallemand64e84512015-05-12 14:25:37 +02006321 char *newline;
6322 int newlinesize = linesize * 2;
6323
6324 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6325 if (newline == NULL) {
6326 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6327 file, linenum);
6328 err_code |= ERR_ALERT | ERR_FATAL;
6329 continue;
6330 }
6331
6332 readbytes = linesize - 1;
6333 linesize = newlinesize;
6334 thisline = newline;
6335 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006336 }
6337
William Lallemand64e84512015-05-12 14:25:37 +02006338 readbytes = 0;
6339
Willy Tarreaubaaee002006-06-26 02:48:02 +02006340 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006341 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006342 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006343
Willy Tarreaubaaee002006-06-26 02:48:02 +02006344 arg = 0;
6345 args[arg] = line;
6346
6347 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006348 if (*line == '"' && !squote) { /* double quote outside single quotes */
6349 if (dquote)
6350 dquote = 0;
6351 else
6352 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006353 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006354 end--;
6355 }
6356 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6357 if (squote)
6358 squote = 0;
6359 else
6360 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006361 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006362 end--;
6363 }
6364 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006365 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6366 * C equivalent value. Other combinations left unchanged (eg: \1).
6367 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006368 int skip = 0;
6369 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6370 *line = line[1];
6371 skip = 1;
6372 }
6373 else if (line[1] == 'r') {
6374 *line = '\r';
6375 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006376 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006377 else if (line[1] == 'n') {
6378 *line = '\n';
6379 skip = 1;
6380 }
6381 else if (line[1] == 't') {
6382 *line = '\t';
6383 skip = 1;
6384 }
6385 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006386 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006387 unsigned char hex1, hex2;
6388 hex1 = toupper(line[2]) - '0';
6389 hex2 = toupper(line[3]) - '0';
6390 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6391 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6392 *line = (hex1<<4) + hex2;
6393 skip = 3;
6394 }
6395 else {
6396 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006397 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006398 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006399 } else if (line[1] == '"') {
6400 *line = '"';
6401 skip = 1;
6402 } else if (line[1] == '\'') {
6403 *line = '\'';
6404 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006405 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6406 *line = '$';
6407 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006408 }
6409 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006410 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006411 end -= skip;
6412 }
6413 line++;
6414 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006415 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006416 /* end of string, end of loop */
6417 *line = 0;
6418 break;
6419 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006420 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006421 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006422 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006423 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006424 line++;
6425 args[++arg] = line;
6426 }
William Lallemandb2f07452015-05-12 14:27:13 +02006427 else if (dquote && *line == '$') {
6428 /* environment variables are evaluated inside double quotes */
6429 char *var_beg;
6430 char *var_end;
6431 char save_char;
6432 char *value;
6433 int val_len;
6434 int newlinesize;
6435 int braces = 0;
6436
6437 var_beg = line + 1;
6438 var_end = var_beg;
6439
6440 if (*var_beg == '{') {
6441 var_beg++;
6442 var_end++;
6443 braces = 1;
6444 }
6445
6446 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6447 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6448 err_code |= ERR_ALERT | ERR_FATAL;
6449 goto next_line; /* skip current line */
6450 }
6451
6452 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6453 var_end++;
6454
6455 save_char = *var_end;
6456 *var_end = '\0';
6457 value = getenv(var_beg);
6458 *var_end = save_char;
6459 val_len = value ? strlen(value) : 0;
6460
6461 if (braces) {
6462 if (*var_end == '}') {
6463 var_end++;
6464 braces = 0;
6465 } else {
6466 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
6467 err_code |= ERR_ALERT | ERR_FATAL;
6468 goto next_line; /* skip current line */
6469 }
6470 }
6471
6472 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
6473
6474 /* if not enough space in thisline */
6475 if (newlinesize > linesize) {
6476 char *newline;
6477
6478 newline = realloc(thisline, newlinesize * sizeof(*thisline));
6479 if (newline == NULL) {
6480 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
6481 err_code |= ERR_ALERT | ERR_FATAL;
6482 goto next_line; /* slip current line */
6483 }
6484 /* recompute pointers if realloc returns a new pointer */
6485 if (newline != thisline) {
6486 int i;
6487 int diff;
6488
6489 for (i = 0; i <= arg; i++) {
6490 diff = args[i] - thisline;
6491 args[i] = newline + diff;
6492 }
6493
6494 diff = var_end - thisline;
6495 var_end = newline + diff;
6496 diff = end - thisline;
6497 end = newline + diff;
6498 diff = line - thisline;
6499 line = newline + diff;
6500 thisline = newline;
6501 }
6502 linesize = newlinesize;
6503 }
6504
6505 /* insert value inside the line */
6506 memmove(line + val_len, var_end, end - var_end + 1);
6507 memcpy(line, value, val_len);
6508 end += val_len - (var_end - line);
6509 line += val_len;
6510 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006511 else {
6512 line++;
6513 }
6514 }
William Lallemandb2f07452015-05-12 14:27:13 +02006515
William Lallemandf9873ba2015-05-05 17:37:14 +02006516 if (dquote) {
6517 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
6518 err_code |= ERR_ALERT | ERR_FATAL;
6519 }
6520
6521 if (squote) {
6522 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
6523 err_code |= ERR_ALERT | ERR_FATAL;
6524 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006525
6526 /* empty line */
6527 if (!**args)
6528 continue;
6529
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006530 if (*line) {
6531 /* we had to stop due to too many args.
6532 * Let's terminate the string, print the offending part then cut the
6533 * last arg.
6534 */
6535 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6536 line++;
6537 *line = '\0';
6538
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006539 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006540 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006541 err_code |= ERR_ALERT | ERR_FATAL;
6542 args[arg] = line;
6543 }
6544
Willy Tarreau540abe42007-05-02 20:50:16 +02006545 /* zero out remaining args and ensure that at least one entry
6546 * is zeroed out.
6547 */
6548 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006549 args[arg] = line;
6550 }
6551
Willy Tarreau3842f002009-06-14 11:39:52 +02006552 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006553 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006554 char *tmp;
6555
Willy Tarreau3842f002009-06-14 11:39:52 +02006556 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006557 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006558 for (arg=0; *args[arg+1]; arg++)
6559 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006560 *tmp = '\0'; // fix the next arg to \0
6561 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006562 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006563 else if (!strcmp(args[0], "default")) {
6564 kwm = KWM_DEF;
6565 for (arg=0; *args[arg+1]; arg++)
6566 args[arg] = args[arg+1]; // shift args after inversion
6567 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006568
William Lallemand0f99e342011-10-12 17:50:54 +02006569 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6570 strcmp(args[0], "log") != 0) {
6571 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006572 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006573 }
6574
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006575 /* detect section start */
6576 list_for_each_entry(ics, &sections, list) {
6577 if (strcmp(args[0], ics->section_name) == 0) {
6578 cursection = ics->section_name;
6579 cs = ics;
6580 break;
6581 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006582 }
6583
Willy Tarreaubaaee002006-06-26 02:48:02 +02006584 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006585 if (cs)
6586 err_code |= cs->section_parser(file, linenum, args, kwm);
6587 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006588 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006589 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006590 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006591
6592 if (err_code & ERR_ABORT)
6593 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006594 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006595 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02006596 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006597 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006598 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006599}
6600
Willy Tarreau64ab6072014-09-16 12:17:36 +02006601/* This function propagates processes from frontend <from> to backend <to> so
6602 * that it is always guaranteed that a backend pointed to by a frontend is
6603 * bound to all of its processes. After that, if the target is a "listen"
6604 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02006605 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02006606 * checked first to ensure that <to> is already bound to all processes of
6607 * <from>, there is no risk of looping and we ensure to follow the shortest
6608 * path to the destination.
6609 *
6610 * It is possible to set <to> to NULL for the first call so that the function
6611 * takes care of visiting the initial frontend in <from>.
6612 *
6613 * It is important to note that the function relies on the fact that all names
6614 * have already been resolved.
6615 */
6616void propagate_processes(struct proxy *from, struct proxy *to)
6617{
6618 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006619
6620 if (to) {
6621 /* check whether we need to go down */
6622 if (from->bind_proc &&
6623 (from->bind_proc & to->bind_proc) == from->bind_proc)
6624 return;
6625
6626 if (!from->bind_proc && !to->bind_proc)
6627 return;
6628
6629 to->bind_proc = from->bind_proc ?
6630 (to->bind_proc | from->bind_proc) : 0;
6631
6632 /* now propagate down */
6633 from = to;
6634 }
6635
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006636 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006637 return;
6638
Willy Tarreauf6b70012014-12-18 14:00:43 +01006639 if (from->state == PR_STSTOPPED)
6640 return;
6641
Willy Tarreau64ab6072014-09-16 12:17:36 +02006642 /* default_backend */
6643 if (from->defbe.be)
6644 propagate_processes(from, from->defbe.be);
6645
6646 /* use_backend */
6647 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006648 if (rule->dynamic)
6649 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006650 to = rule->be.backend;
6651 propagate_processes(from, to);
6652 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02006653}
6654
Willy Tarreaubb925012009-07-23 13:36:36 +02006655/*
6656 * Returns the error code, 0 if OK, or any combination of :
6657 * - ERR_ABORT: must abort ASAP
6658 * - ERR_FATAL: we can continue parsing but not start the service
6659 * - ERR_WARN: a warning has been emitted
6660 * - ERR_ALERT: an alert has been emitted
6661 * Only the two first ones can stop processing, the two others are just
6662 * indicators.
6663 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006664int check_config_validity()
6665{
6666 int cfgerr = 0;
6667 struct proxy *curproxy = NULL;
6668 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006669 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006670 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006671 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006672
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006673 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006674 /*
6675 * Now, check for the integrity of all that we have collected.
6676 */
6677
6678 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006679 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006680
Willy Tarreau193b8c62012-11-22 00:17:38 +01006681 if (!global.tune.max_http_hdr)
6682 global.tune.max_http_hdr = MAX_HTTP_HDR;
6683
6684 if (!global.tune.cookie_len)
6685 global.tune.cookie_len = CAPTURE_LEN;
6686
6687 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6688
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006689 /* Post initialisation of the users and groups lists. */
6690 err_code = userlist_postinit();
6691 if (err_code != ERR_NONE)
6692 goto out;
6693
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006694 /* first, we will invert the proxy list order */
6695 curproxy = NULL;
6696 while (proxy) {
6697 struct proxy *next;
6698
6699 next = proxy->next;
6700 proxy->next = curproxy;
6701 curproxy = proxy;
6702 if (!next)
6703 break;
6704 proxy = next;
6705 }
6706
Willy Tarreau419ead82014-09-16 13:41:21 +02006707 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006708 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006709 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006710 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006711 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006712 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006713 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006714 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006715
Willy Tarreau050536d2012-10-04 08:47:34 +02006716 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006717 /* proxy ID not set, use automatic numbering with first
6718 * spare entry starting with next_pxid.
6719 */
6720 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6721 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6722 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006723 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006724 next_pxid++;
6725
Willy Tarreau55ea7572007-06-17 19:56:27 +02006726
Willy Tarreaubaaee002006-06-26 02:48:02 +02006727 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006728 /* ensure we don't keep listeners uselessly bound */
6729 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02006730 free((void *)curproxy->table.peers.name);
6731 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006732 continue;
6733 }
6734
Willy Tarreau102df612014-05-07 23:56:38 +02006735 /* Check multi-process mode compatibility for the current proxy */
6736
6737 if (curproxy->bind_proc) {
6738 /* an explicit bind-process was specified, let's check how many
6739 * processes remain.
6740 */
6741 nbproc = popcount(curproxy->bind_proc);
6742
6743 curproxy->bind_proc &= nbits(global.nbproc);
6744 if (!curproxy->bind_proc && nbproc == 1) {
6745 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);
6746 curproxy->bind_proc = 1;
6747 }
6748 else if (!curproxy->bind_proc && nbproc > 1) {
6749 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);
6750 curproxy->bind_proc = 0;
6751 }
6752 }
6753
Willy Tarreau3d209582014-05-09 17:06:11 +02006754 /* check and reduce the bind-proc of each listener */
6755 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6756 unsigned long mask;
6757
6758 if (!bind_conf->bind_proc)
6759 continue;
6760
6761 mask = nbits(global.nbproc);
6762 if (curproxy->bind_proc)
6763 mask &= curproxy->bind_proc;
6764 /* mask cannot be null here thanks to the previous checks */
6765
6766 nbproc = popcount(bind_conf->bind_proc);
6767 bind_conf->bind_proc &= mask;
6768
6769 if (!bind_conf->bind_proc && nbproc == 1) {
6770 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",
6771 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6772 bind_conf->bind_proc = mask & ~(mask - 1);
6773 }
6774 else if (!bind_conf->bind_proc && nbproc > 1) {
6775 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",
6776 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6777 bind_conf->bind_proc = 0;
6778 }
6779 }
6780
Willy Tarreauff01a212009-03-15 13:46:16 +01006781 switch (curproxy->mode) {
6782 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006783 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006784 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006785 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6786 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006787 cfgerr++;
6788 }
6789
6790 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006791 Warning("config : servers will be ignored for %s '%s'.\n",
6792 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006793 break;
6794
6795 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006796 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006797 break;
6798
6799 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006800 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006801 break;
6802 }
6803
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006804 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006805 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006806 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006807 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6808 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006809 cfgerr++;
6810 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006811#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006812 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006813 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6814 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006815 cfgerr++;
6816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006817#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006818 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006819 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6820 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006821 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006822 }
6823 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006824 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006825 /* If no LB algo is set in a backend, and we're not in
6826 * transparent mode, dispatch mode nor proxy mode, we
6827 * want to use balance roundrobin by default.
6828 */
6829 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6830 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006831 }
6832 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006833
Willy Tarreau1620ec32011-08-06 17:05:02 +02006834 if (curproxy->options & PR_O_DISPATCH)
6835 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6836 else if (curproxy->options & PR_O_HTTP_PROXY)
6837 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6838 else if (curproxy->options & PR_O_TRANSP)
6839 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006840
Willy Tarreau1620ec32011-08-06 17:05:02 +02006841 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6842 if (curproxy->options & PR_O_DISABLE404) {
6843 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6844 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6845 err_code |= ERR_WARN;
6846 curproxy->options &= ~PR_O_DISABLE404;
6847 }
6848 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6849 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6850 "send-state", proxy_type_str(curproxy), curproxy->id);
6851 err_code |= ERR_WARN;
6852 curproxy->options &= ~PR_O2_CHK_SNDST;
6853 }
Willy Tarreauef781042010-01-27 11:53:01 +01006854 }
6855
Simon Horman98637e52014-06-20 12:30:16 +09006856 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6857 if (!global.external_check) {
6858 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6859 curproxy->id, "option external-check");
6860 cfgerr++;
6861 }
6862 if (!curproxy->check_command) {
6863 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6864 curproxy->id, "option external-check");
6865 cfgerr++;
6866 }
6867 }
6868
Simon Horman64e34162015-02-06 11:11:57 +09006869 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006870 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
6871 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09006872 "'email-alert from', 'email-alert level' 'email-alert mailer', "
6873 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006874 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
6875 "to be present).\n",
6876 proxy_type_str(curproxy), curproxy->id);
6877 err_code |= ERR_WARN;
6878 free_email_alert(curproxy);
6879 }
6880 if (!curproxy->email_alert.myhostname)
6881 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09006882 }
6883
Simon Horman98637e52014-06-20 12:30:16 +09006884 if (curproxy->check_command) {
6885 int clear = 0;
6886 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6887 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6888 "external-check command", proxy_type_str(curproxy), curproxy->id);
6889 err_code |= ERR_WARN;
6890 clear = 1;
6891 }
6892 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6893 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6894 curproxy->id, "external-check command");
6895 cfgerr++;
6896 }
6897 if (clear) {
6898 free(curproxy->check_command);
6899 curproxy->check_command = NULL;
6900 }
6901 }
6902
6903 if (curproxy->check_path) {
6904 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6905 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6906 "external-check path", proxy_type_str(curproxy), curproxy->id);
6907 err_code |= ERR_WARN;
6908 free(curproxy->check_path);
6909 curproxy->check_path = NULL;
6910 }
6911 }
6912
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006913 /* if a default backend was specified, let's find it */
6914 if (curproxy->defbe.name) {
6915 struct proxy *target;
6916
Willy Tarreauafb39922015-05-26 12:04:09 +02006917 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006918 if (!target) {
6919 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6920 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006921 cfgerr++;
6922 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006923 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6924 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006925 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02006926 } else if (target->mode != curproxy->mode &&
6927 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
6928
6929 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
6930 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
6931 curproxy->conf.file, curproxy->conf.line,
6932 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
6933 target->conf.file, target->conf.line);
6934 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006935 } else {
6936 free(curproxy->defbe.name);
6937 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006938
6939 /* Emit a warning if this proxy also has some servers */
6940 if (curproxy->srv) {
6941 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6942 curproxy->id);
6943 err_code |= ERR_WARN;
6944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006945 }
6946 }
6947
Willy Tarreau55ea7572007-06-17 19:56:27 +02006948 /* find the target proxy for 'use_backend' rules */
6949 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006950 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006951 struct logformat_node *node;
6952 char *pxname;
6953
6954 /* Try to parse the string as a log format expression. If the result
6955 * of the parsing is only one entry containing a simple string, then
6956 * it's a standard string corresponding to a static rule, thus the
6957 * parsing is cancelled and be.name is restored to be resolved.
6958 */
6959 pxname = rule->be.name;
6960 LIST_INIT(&rule->be.expr);
6961 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6962 curproxy->conf.args.file, curproxy->conf.args.line);
6963 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6964
6965 if (!LIST_ISEMPTY(&rule->be.expr)) {
6966 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6967 rule->dynamic = 1;
6968 free(pxname);
6969 continue;
6970 }
6971 /* simple string: free the expression and fall back to static rule */
6972 free(node->arg);
6973 free(node);
6974 }
6975
6976 rule->dynamic = 0;
6977 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006978
Willy Tarreauafb39922015-05-26 12:04:09 +02006979 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006980 if (!target) {
6981 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6982 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006983 cfgerr++;
6984 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006985 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6986 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006987 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02006988 } else if (target->mode != curproxy->mode &&
6989 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
6990
6991 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
6992 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
6993 curproxy->conf.file, curproxy->conf.line,
6994 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
6995 target->conf.file, target->conf.line);
6996 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006997 } else {
6998 free((void *)rule->be.name);
6999 rule->be.backend = target;
7000 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007001 }
7002
Willy Tarreau64ab6072014-09-16 12:17:36 +02007003 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007004 list_for_each_entry(srule, &curproxy->server_rules, list) {
7005 struct server *target = findserver(curproxy, srule->srv.name);
7006
7007 if (!target) {
7008 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7009 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7010 cfgerr++;
7011 continue;
7012 }
7013 free((void *)srule->srv.name);
7014 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007015 }
7016
Emeric Brunb982a3d2010-01-04 15:45:53 +01007017 /* find the target table for 'stick' rules */
7018 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7019 struct proxy *target;
7020
Emeric Brun1d33b292010-01-04 15:47:17 +01007021 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7022 if (mrule->flags & STK_IS_STORE)
7023 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7024
Emeric Brunb982a3d2010-01-04 15:45:53 +01007025 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007026 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007027 else
7028 target = curproxy;
7029
7030 if (!target) {
7031 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7032 curproxy->id, mrule->table.name);
7033 cfgerr++;
7034 }
7035 else if (target->table.size == 0) {
7036 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7037 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7038 cfgerr++;
7039 }
Willy Tarreau12785782012-04-27 21:37:17 +02007040 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7041 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007042 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7043 cfgerr++;
7044 }
7045 else {
7046 free((void *)mrule->table.name);
7047 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007048 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007049 }
7050 }
7051
7052 /* find the target table for 'store response' rules */
7053 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7054 struct proxy *target;
7055
Emeric Brun1d33b292010-01-04 15:47:17 +01007056 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7057
Emeric Brunb982a3d2010-01-04 15:45:53 +01007058 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007059 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007060 else
7061 target = curproxy;
7062
7063 if (!target) {
7064 Alert("Proxy '%s': unable to find store table '%s'.\n",
7065 curproxy->id, mrule->table.name);
7066 cfgerr++;
7067 }
7068 else if (target->table.size == 0) {
7069 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7070 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7071 cfgerr++;
7072 }
Willy Tarreau12785782012-04-27 21:37:17 +02007073 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7074 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007075 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7076 cfgerr++;
7077 }
7078 else {
7079 free((void *)mrule->table.name);
7080 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007081 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007082 }
7083 }
7084
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007085 /* find the target table for 'tcp-request' layer 4 rules */
7086 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7087 struct proxy *target;
7088
Willy Tarreaub4c84932013-07-23 19:15:30 +02007089 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007090 continue;
7091
7092 if (trule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007093 target = proxy_tbl_by_name(trule->act_prm.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007094 else
7095 target = curproxy;
7096
7097 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007098 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7099 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007100 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007101 cfgerr++;
7102 }
7103 else if (target->table.size == 0) {
7104 Alert("Proxy '%s': table '%s' used but not configured.\n",
7105 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7106 cfgerr++;
7107 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007108 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7109 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7110 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 +01007111 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007112 cfgerr++;
7113 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007114 else {
7115 free(trule->act_prm.trk_ctr.table.n);
7116 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007117 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007118 * to pass a list of counters to track and allocate them right here using
7119 * stktable_alloc_data_type().
7120 */
7121 }
7122 }
7123
Willy Tarreaud1f96522010-08-03 19:34:32 +02007124 /* find the target table for 'tcp-request' layer 6 rules */
7125 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7126 struct proxy *target;
7127
Willy Tarreaub4c84932013-07-23 19:15:30 +02007128 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007129 continue;
7130
7131 if (trule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007132 target = proxy_tbl_by_name(trule->act_prm.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007133 else
7134 target = curproxy;
7135
7136 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007137 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7138 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007139 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007140 cfgerr++;
7141 }
7142 else if (target->table.size == 0) {
7143 Alert("Proxy '%s': table '%s' used but not configured.\n",
7144 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7145 cfgerr++;
7146 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007147 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7148 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7149 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 +01007150 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007151 cfgerr++;
7152 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007153 else {
7154 free(trule->act_prm.trk_ctr.table.n);
7155 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007156 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007157 * to pass a list of counters to track and allocate them right here using
7158 * stktable_alloc_data_type().
7159 */
7160 }
7161 }
7162
Willy Tarreau09448f72014-06-25 18:12:15 +02007163 /* find the target table for 'http-request' layer 7 rules */
7164 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7165 struct proxy *target;
7166
7167 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
7168 continue;
7169
7170 if (hrqrule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007171 target = proxy_tbl_by_name(hrqrule->act_prm.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007172 else
7173 target = curproxy;
7174
7175 if (!target) {
7176 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7177 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
7178 http_req_trk_idx(hrqrule->action));
7179 cfgerr++;
7180 }
7181 else if (target->table.size == 0) {
7182 Alert("Proxy '%s': table '%s' used but not configured.\n",
7183 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
7184 cfgerr++;
7185 }
7186 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
7187 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7188 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
7189 http_req_trk_idx(hrqrule->action));
7190 cfgerr++;
7191 }
7192 else {
7193 free(hrqrule->act_prm.trk_ctr.table.n);
7194 hrqrule->act_prm.trk_ctr.table.t = &target->table;
7195 /* Note: if we decide to enhance the track-sc syntax, we may be able
7196 * to pass a list of counters to track and allocate them right here using
7197 * stktable_alloc_data_type().
7198 */
7199 }
7200 }
7201
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007202 /* move any "block" rules at the beginning of the http-request rules */
7203 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7204 /* insert block_rules into http_req_rules at the beginning */
7205 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7206 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7207 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7208 curproxy->http_req_rules.n = curproxy->block_rules.n;
7209 LIST_INIT(&curproxy->block_rules);
7210 }
7211
Emeric Brun32da3c42010-09-23 18:39:19 +02007212 if (curproxy->table.peers.name) {
7213 struct peers *curpeers = peers;
7214
7215 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7216 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7217 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007218 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007219 break;
7220 }
7221 }
7222
7223 if (!curpeers) {
7224 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7225 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007226 free((void *)curproxy->table.peers.name);
7227 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007228 cfgerr++;
7229 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007230 else if (curpeers->state == PR_STSTOPPED) {
7231 /* silently disable this peers section */
7232 curproxy->table.peers.p = NULL;
7233 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007234 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007235 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7236 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007237 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007238 cfgerr++;
7239 }
7240 }
7241
Simon Horman9dc49962015-01-30 11:22:59 +09007242
7243 if (curproxy->email_alert.mailers.name) {
7244 struct mailers *curmailers = mailers;
7245
7246 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7247 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7248 free(curproxy->email_alert.mailers.name);
7249 curproxy->email_alert.mailers.m = curmailers;
7250 curmailers->users++;
7251 break;
7252 }
7253 }
7254
7255 if (!curmailers) {
7256 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7257 curproxy->id, curproxy->email_alert.mailers.name);
7258 free_email_alert(curproxy);
7259 cfgerr++;
7260 }
7261 }
7262
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007263 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007264 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007265 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7266 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7267 "proxy", curproxy->id);
7268 cfgerr++;
7269 goto out_uri_auth_compat;
7270 }
7271
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007272 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007273 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007274 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007275 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007276
Willy Tarreau95fa4692010-02-01 13:05:50 +01007277 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7278 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007279
7280 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007281 uri_auth_compat_req[i++] = "realm";
7282 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7283 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007284
Willy Tarreau95fa4692010-02-01 13:05:50 +01007285 uri_auth_compat_req[i++] = "unless";
7286 uri_auth_compat_req[i++] = "{";
7287 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7288 uri_auth_compat_req[i++] = "}";
7289 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007290
Willy Tarreauff011f22011-01-06 17:51:27 +01007291 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7292 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007293 cfgerr++;
7294 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007295 }
7296
Willy Tarreauff011f22011-01-06 17:51:27 +01007297 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007298
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007299 if (curproxy->uri_auth->auth_realm) {
7300 free(curproxy->uri_auth->auth_realm);
7301 curproxy->uri_auth->auth_realm = NULL;
7302 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007303
7304 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007305 }
7306out_uri_auth_compat:
7307
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007308 /* compile the log format */
7309 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007310 if (curproxy->conf.logformat_string != default_http_log_format &&
7311 curproxy->conf.logformat_string != default_tcp_log_format &&
7312 curproxy->conf.logformat_string != clf_http_log_format)
7313 free(curproxy->conf.logformat_string);
7314 curproxy->conf.logformat_string = NULL;
7315 free(curproxy->conf.lfs_file);
7316 curproxy->conf.lfs_file = NULL;
7317 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007318 }
7319
Willy Tarreau62a61232013-04-12 18:13:46 +02007320 if (curproxy->conf.logformat_string) {
7321 curproxy->conf.args.ctx = ARGC_LOG;
7322 curproxy->conf.args.file = curproxy->conf.lfs_file;
7323 curproxy->conf.args.line = curproxy->conf.lfs_line;
7324 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007325 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007326 curproxy->conf.args.file = NULL;
7327 curproxy->conf.args.line = 0;
7328 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007329
Willy Tarreau62a61232013-04-12 18:13:46 +02007330 if (curproxy->conf.uniqueid_format_string) {
7331 curproxy->conf.args.ctx = ARGC_UIF;
7332 curproxy->conf.args.file = curproxy->conf.uif_file;
7333 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007334 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007335 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007336 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007337 curproxy->conf.args.file = NULL;
7338 curproxy->conf.args.line = 0;
7339 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007340
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007341 /* only now we can check if some args remain unresolved.
7342 * This must be done after the users and groups resolution.
7343 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007344 cfgerr += smp_resolve_args(curproxy);
7345 if (!cfgerr)
7346 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007347
Willy Tarreau2738a142006-07-08 17:28:09 +02007348 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007349 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007350 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007351 (!curproxy->timeout.connect ||
7352 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007353 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007354 " | While not properly invalid, you will certainly encounter various problems\n"
7355 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007356 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007357 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007358 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007359 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007360
Willy Tarreau1fa31262007-12-03 00:36:16 +01007361 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7362 * We must still support older configurations, so let's find out whether those
7363 * parameters have been set or must be copied from contimeouts.
7364 */
7365 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007366 if (!curproxy->timeout.tarpit ||
7367 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007368 /* tarpit timeout not set. We search in the following order:
7369 * default.tarpit, curr.connect, default.connect.
7370 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007371 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007372 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007373 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007374 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007375 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007376 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007377 }
7378 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007379 (!curproxy->timeout.queue ||
7380 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007381 /* queue timeout not set. We search in the following order:
7382 * default.queue, curr.connect, default.connect.
7383 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007384 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007385 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007386 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007387 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007388 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007389 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007390 }
7391 }
7392
Willy Tarreau1620ec32011-08-06 17:05:02 +02007393 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007394 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7395 curproxy->check_req = (char *)malloc(curproxy->check_len);
7396 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007397 }
7398
Willy Tarreau215663d2014-06-13 18:30:23 +02007399 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7400 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7401 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7402 proxy_type_str(curproxy), curproxy->id);
7403 err_code |= ERR_WARN;
7404 }
7405
Willy Tarreau193b8c62012-11-22 00:17:38 +01007406 /* ensure that cookie capture length is not too large */
7407 if (curproxy->capture_len >= global.tune.cookie_len) {
7408 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7409 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7410 err_code |= ERR_WARN;
7411 curproxy->capture_len = global.tune.cookie_len - 1;
7412 }
7413
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007414 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007415 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007416 curproxy->req_cap_pool = create_pool("ptrcap",
7417 curproxy->nb_req_cap * sizeof(char *),
7418 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007419 }
7420
7421 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007422 curproxy->rsp_cap_pool = create_pool("ptrcap",
7423 curproxy->nb_rsp_cap * sizeof(char *),
7424 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007425 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007426
Willy Tarreaubaaee002006-06-26 02:48:02 +02007427 /* first, we will invert the servers list order */
7428 newsrv = NULL;
7429 while (curproxy->srv) {
7430 struct server *next;
7431
7432 next = curproxy->srv->next;
7433 curproxy->srv->next = newsrv;
7434 newsrv = curproxy->srv;
7435 if (!next)
7436 break;
7437 curproxy->srv = next;
7438 }
7439
Willy Tarreau17edc812014-01-03 12:14:34 +01007440 /* Check that no server name conflicts. This causes trouble in the stats.
7441 * We only emit a warning for the first conflict affecting each server,
7442 * in order to avoid combinatory explosion if all servers have the same
7443 * name. We do that only for servers which do not have an explicit ID,
7444 * because these IDs were made also for distinguishing them and we don't
7445 * want to annoy people who correctly manage them.
7446 */
7447 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7448 struct server *other_srv;
7449
7450 if (newsrv->puid)
7451 continue;
7452
7453 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7454 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7455 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7456 newsrv->conf.file, newsrv->conf.line,
7457 proxy_type_str(curproxy), curproxy->id,
7458 newsrv->id, other_srv->conf.line);
7459 break;
7460 }
7461 }
7462 }
7463
Willy Tarreaudd701652010-05-25 23:03:02 +02007464 /* assign automatic UIDs to servers which don't have one yet */
7465 next_id = 1;
7466 newsrv = curproxy->srv;
7467 while (newsrv != NULL) {
7468 if (!newsrv->puid) {
7469 /* server ID not set, use automatic numbering with first
7470 * spare entry starting with next_svid.
7471 */
7472 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7473 newsrv->conf.id.key = newsrv->puid = next_id;
7474 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7475 }
7476 next_id++;
7477 newsrv = newsrv->next;
7478 }
7479
Willy Tarreau20697042007-11-15 23:26:18 +01007480 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007481 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007482
Willy Tarreau62c3be22012-01-20 13:12:32 +01007483 /*
7484 * If this server supports a maxconn parameter, it needs a dedicated
7485 * tasks to fill the emptied slots when a connection leaves.
7486 * Also, resolve deferred tracking dependency if needed.
7487 */
7488 newsrv = curproxy->srv;
7489 while (newsrv != NULL) {
7490 if (newsrv->minconn > newsrv->maxconn) {
7491 /* Only 'minconn' was specified, or it was higher than or equal
7492 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7493 * this will avoid further useless expensive computations.
7494 */
7495 newsrv->maxconn = newsrv->minconn;
7496 } else if (newsrv->maxconn && !newsrv->minconn) {
7497 /* minconn was not specified, so we set it to maxconn */
7498 newsrv->minconn = newsrv->maxconn;
7499 }
7500
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007501#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007502 if (newsrv->use_ssl || newsrv->check.use_ssl)
7503 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007504#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007505
Willy Tarreau2f075e92013-12-03 11:11:34 +01007506 /* set the check type on the server */
7507 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7508
Willy Tarreau62c3be22012-01-20 13:12:32 +01007509 if (newsrv->trackit) {
7510 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007511 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007512 char *pname, *sname;
7513
7514 pname = newsrv->trackit;
7515 sname = strrchr(pname, '/');
7516
7517 if (sname)
7518 *sname++ = '\0';
7519 else {
7520 sname = pname;
7521 pname = NULL;
7522 }
7523
7524 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007525 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007526 if (!px) {
7527 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7528 proxy_type_str(curproxy), curproxy->id,
7529 newsrv->id, pname);
7530 cfgerr++;
7531 goto next_srv;
7532 }
7533 } else
7534 px = curproxy;
7535
7536 srv = findserver(px, sname);
7537 if (!srv) {
7538 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7539 proxy_type_str(curproxy), curproxy->id,
7540 newsrv->id, sname);
7541 cfgerr++;
7542 goto next_srv;
7543 }
7544
Willy Tarreau32091232014-05-16 13:52:00 +02007545 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7546 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7547 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007548 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007549 "tracking as it does not have any check nor agent enabled.\n",
7550 proxy_type_str(curproxy), curproxy->id,
7551 newsrv->id, px->id, srv->id);
7552 cfgerr++;
7553 goto next_srv;
7554 }
7555
7556 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7557
7558 if (loop) {
7559 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7560 "belongs to a tracking chain looping back to %s/%s.\n",
7561 proxy_type_str(curproxy), curproxy->id,
7562 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007563 cfgerr++;
7564 goto next_srv;
7565 }
7566
7567 if (curproxy != px &&
7568 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7569 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7570 "tracking: disable-on-404 option inconsistency.\n",
7571 proxy_type_str(curproxy), curproxy->id,
7572 newsrv->id, px->id, srv->id);
7573 cfgerr++;
7574 goto next_srv;
7575 }
7576
7577 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007578 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007579 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007580 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007581 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007582 }
7583
7584 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007585 newsrv->tracknext = srv->trackers;
7586 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007587
7588 free(newsrv->trackit);
7589 newsrv->trackit = NULL;
7590 }
7591 next_srv:
7592 newsrv = newsrv->next;
7593 }
7594
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007595 /* We have to initialize the server lookup mechanism depending
7596 * on what LB algorithm was choosen.
7597 */
7598
7599 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7600 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7601 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007602 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7603 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7604 init_server_map(curproxy);
7605 } else {
7606 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7607 fwrr_init_server_groups(curproxy);
7608 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007609 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007610
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007611 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007612 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7613 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7614 fwlc_init_server_tree(curproxy);
7615 } else {
7616 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7617 fas_init_server_tree(curproxy);
7618 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007619 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007620
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007621 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007622 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7623 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7624 chash_init_server_tree(curproxy);
7625 } else {
7626 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7627 init_server_map(curproxy);
7628 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007629 break;
7630 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007631
7632 if (curproxy->options & PR_O_LOGASAP)
7633 curproxy->to_log &= ~LW_BYTES;
7634
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007635 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007636 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007637 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7638 proxy_type_str(curproxy), curproxy->id);
7639 err_code |= ERR_WARN;
7640 }
7641
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007642 if (curproxy->mode != PR_MODE_HTTP) {
7643 int optnum;
7644
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007645 if (curproxy->uri_auth) {
7646 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7647 proxy_type_str(curproxy), curproxy->id);
7648 err_code |= ERR_WARN;
7649 curproxy->uri_auth = NULL;
7650 }
7651
Willy Tarreau87cf5142011-08-19 22:57:24 +02007652 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007653 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7654 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7655 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007656 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007657 }
7658
7659 if (curproxy->options & PR_O_ORGTO) {
7660 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7661 "originalto", proxy_type_str(curproxy), curproxy->id);
7662 err_code |= ERR_WARN;
7663 curproxy->options &= ~PR_O_ORGTO;
7664 }
7665
7666 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7667 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7668 (curproxy->cap & cfg_opts[optnum].cap) &&
7669 (curproxy->options & cfg_opts[optnum].val)) {
7670 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7671 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7672 err_code |= ERR_WARN;
7673 curproxy->options &= ~cfg_opts[optnum].val;
7674 }
7675 }
7676
7677 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7678 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7679 (curproxy->cap & cfg_opts2[optnum].cap) &&
7680 (curproxy->options2 & cfg_opts2[optnum].val)) {
7681 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7682 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7683 err_code |= ERR_WARN;
7684 curproxy->options2 &= ~cfg_opts2[optnum].val;
7685 }
7686 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007687
Pieter Baauwd551fb52013-05-08 22:49:23 +02007688#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007689 if (curproxy->conn_src.bind_hdr_occ) {
7690 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007691 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007692 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007693 err_code |= ERR_WARN;
7694 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007695#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007696 }
7697
Willy Tarreaubaaee002006-06-26 02:48:02 +02007698 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007699 * ensure that we're not cross-dressing a TCP server into HTTP.
7700 */
7701 newsrv = curproxy->srv;
7702 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007703 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007704 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7705 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007706 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007707 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007708
Willy Tarreau0cec3312011-10-31 13:49:26 +01007709 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7710 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7711 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7712 err_code |= ERR_WARN;
7713 }
7714
Willy Tarreauc93cd162014-05-13 15:54:22 +02007715 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007716 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7717 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7718 err_code |= ERR_WARN;
7719 }
7720
Pieter Baauwd551fb52013-05-08 22:49:23 +02007721#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007722 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7723 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007724 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 +01007725 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007726 err_code |= ERR_WARN;
7727 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007728#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007729 newsrv = newsrv->next;
7730 }
7731
Willy Tarreaue42bd962014-09-16 16:21:19 +02007732 /* check if we have a frontend with "tcp-request content" looking at L7
7733 * with no inspect-delay
7734 */
7735 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7736 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7737 if (trule->action == TCP_ACT_CAPTURE &&
7738 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7739 break;
7740 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7741 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7742 break;
7743 }
7744
7745 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7746 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7747 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7748 " This means that these rules will randomly find their contents. This can be fixed by"
7749 " setting the tcp-request inspect-delay.\n",
7750 proxy_type_str(curproxy), curproxy->id);
7751 err_code |= ERR_WARN;
7752 }
7753 }
7754
Willy Tarreauc1a21672009-08-16 22:37:44 +02007755 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007756 if (!curproxy->accept)
7757 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007758
Willy Tarreauc1a21672009-08-16 22:37:44 +02007759 if (curproxy->tcp_req.inspect_delay ||
7760 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007761 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007762
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007763 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007764 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007765 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007766 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007767
7768 /* both TCP and HTTP must check switching rules */
7769 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7770 }
7771
7772 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007773 if (curproxy->tcp_req.inspect_delay ||
7774 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7775 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7776
Emeric Brun97679e72010-09-23 17:56:44 +02007777 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7778 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7779
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007780 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007781 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007782 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007783 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007784
7785 /* If the backend does requires RDP cookie persistence, we have to
7786 * enable the corresponding analyser.
7787 */
7788 if (curproxy->options2 & PR_O2_RDPC_PRST)
7789 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7790 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007791 }
7792
7793 /***********************************************************/
7794 /* At this point, target names have already been resolved. */
7795 /***********************************************************/
7796
7797 /* Check multi-process mode compatibility */
7798
7799 if (global.nbproc > 1 && global.stats_fe) {
7800 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7801 unsigned long mask;
7802
7803 mask = nbits(global.nbproc);
7804 if (global.stats_fe->bind_proc)
7805 mask &= global.stats_fe->bind_proc;
7806
7807 if (bind_conf->bind_proc)
7808 mask &= bind_conf->bind_proc;
7809
7810 /* stop here if more than one process is used */
7811 if (popcount(mask) > 1)
7812 break;
7813 }
7814 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7815 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");
7816 }
7817 }
7818
7819 /* Make each frontend inherit bind-process from its listeners when not specified. */
7820 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7821 if (curproxy->bind_proc)
7822 continue;
7823
7824 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7825 unsigned long mask;
7826
Willy Tarreaue428b082015-05-04 21:57:58 +02007827 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007828 curproxy->bind_proc |= mask;
7829 }
7830
7831 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02007832 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007833 }
7834
7835 if (global.stats_fe) {
7836 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7837 unsigned long mask;
7838
Willy Tarreaue428b082015-05-04 21:57:58 +02007839 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007840 global.stats_fe->bind_proc |= mask;
7841 }
7842 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02007843 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007844 }
7845
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007846 /* propagate bindings from frontends to backends. Don't do it if there
7847 * are any fatal errors as we must not call it with unresolved proxies.
7848 */
7849 if (!cfgerr) {
7850 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7851 if (curproxy->cap & PR_CAP_FE)
7852 propagate_processes(curproxy, NULL);
7853 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007854 }
7855
7856 /* Bind each unbound backend to all processes when not specified. */
7857 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7858 if (curproxy->bind_proc)
7859 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02007860 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007861 }
7862
7863 /*******************************************************/
7864 /* At this step, all proxies have a non-null bind_proc */
7865 /*******************************************************/
7866
7867 /* perform the final checks before creating tasks */
7868
7869 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7870 struct listener *listener;
7871 unsigned int next_id;
7872 int nbproc;
7873
7874 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007875
Emeric Brunc52962f2012-11-15 18:28:02 +01007876#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007877 /* Configure SSL for each bind line.
7878 * Note: if configuration fails at some point, the ->ctx member
7879 * remains NULL so that listeners can later detach.
7880 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007881 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007882 int alloc_ctx;
7883
Emeric Brunc52962f2012-11-15 18:28:02 +01007884 if (!bind_conf->is_ssl) {
7885 if (bind_conf->default_ctx) {
7886 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7887 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7888 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007889 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007890 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007891 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007892 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007893 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007894 cfgerr++;
7895 continue;
7896 }
7897
Emeric Brun8dc60392014-05-09 13:52:00 +02007898 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007899 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007900 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7901 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");
7902 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007903 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007904 cfgerr++;
7905 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007906 }
7907
Emeric Brunfc0421f2012-09-07 17:30:07 +02007908 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007909 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007910 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007911#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007912
Willy Tarreaue6b98942007-10-29 01:09:36 +01007913 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007914 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007915 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007916 if (!listener->luid) {
7917 /* listener ID not set, use automatic numbering with first
7918 * spare entry starting with next_luid.
7919 */
7920 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7921 listener->conf.id.key = listener->luid = next_id;
7922 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007923 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007924 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007925
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007926 /* enable separate counters */
7927 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7928 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007929 if (!listener->name)
7930 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007931 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007932
Willy Tarreaue6b98942007-10-29 01:09:36 +01007933 if (curproxy->options & PR_O_TCP_NOLING)
7934 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007935 if (!listener->maxconn)
7936 listener->maxconn = curproxy->maxconn;
7937 if (!listener->backlog)
7938 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007939 if (!listener->maxaccept)
7940 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7941
7942 /* we want to have an optimal behaviour on single process mode to
7943 * maximize the work at once, but in multi-process we want to keep
7944 * some fairness between processes, so we target half of the max
7945 * number of events to be balanced over all the processes the proxy
7946 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7947 * used to disable the limit.
7948 */
7949 if (listener->maxaccept > 0) {
7950 if (nbproc > 1)
7951 listener->maxaccept = (listener->maxaccept + 1) / 2;
7952 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7953 }
7954
Willy Tarreau9903f0e2015-04-04 18:50:31 +02007955 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02007956 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007957 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01007958 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007959
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007960 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7961 listener->options |= LI_O_TCP_RULES;
7962
Willy Tarreaude3041d2010-05-31 10:56:17 +02007963 if (curproxy->mon_mask.s_addr)
7964 listener->options |= LI_O_CHK_MONNET;
7965
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007966 /* smart accept mode is automatic in HTTP mode */
7967 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007968 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007969 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7970 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007971 }
7972
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007973 /* Release unused SSL configs */
7974 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7975 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007976 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007977#ifdef USE_OPENSSL
7978 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007979 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007980 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007981 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007982 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007983 if(bind_conf->keys_ref) {
7984 free(bind_conf->keys_ref->filename);
7985 free(bind_conf->keys_ref->tlskeys);
7986 free(bind_conf->keys_ref);
7987 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007988#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007989 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007990
Willy Tarreau102df612014-05-07 23:56:38 +02007991 if (nbproc > 1) {
7992 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02007993 int count, maxproc = 0;
7994
7995 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7996 count = popcount(bind_conf->bind_proc);
7997 if (count > maxproc)
7998 maxproc = count;
7999 }
8000 /* backends have 0, frontends have 1 or more */
8001 if (maxproc != 1)
8002 Warning("Proxy '%s': in multi-process mode, stats will be"
8003 " limited to process assigned to the current request.\n",
8004 curproxy->id);
8005
Willy Tarreau102df612014-05-07 23:56:38 +02008006 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8007 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8008 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008009 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008010 }
Willy Tarreau102df612014-05-07 23:56:38 +02008011 if (curproxy->appsession_name) {
8012 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
8013 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008014 }
Willy Tarreau102df612014-05-07 23:56:38 +02008015 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8016 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8017 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008018 }
8019 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008020
8021 /* create the task associated with the proxy */
8022 curproxy->task = task_new();
8023 if (curproxy->task) {
8024 curproxy->task->context = curproxy;
8025 curproxy->task->process = manage_proxy;
8026 /* no need to queue, it will be done automatically if some
8027 * listener gets limited.
8028 */
8029 curproxy->task->expire = TICK_ETERNITY;
8030 } else {
8031 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8032 curproxy->id);
8033 cfgerr++;
8034 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008035 }
8036
Willy Tarreaufbb78422011-06-05 15:38:35 +02008037 /* automatically compute fullconn if not set. We must not do it in the
8038 * loop above because cross-references are not yet fully resolved.
8039 */
8040 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8041 /* If <fullconn> is not set, let's set it to 10% of the sum of
8042 * the possible incoming frontend's maxconns.
8043 */
8044 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8045 struct proxy *fe;
8046 int total = 0;
8047
8048 /* sum up the number of maxconns of frontends which
8049 * reference this backend at least once or which are
8050 * the same one ('listen').
8051 */
8052 for (fe = proxy; fe; fe = fe->next) {
8053 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008054 int found = 0;
8055
8056 if (!(fe->cap & PR_CAP_FE))
8057 continue;
8058
8059 if (fe == curproxy) /* we're on a "listen" instance */
8060 found = 1;
8061
8062 if (fe->defbe.be == curproxy) /* "default_backend" */
8063 found = 1;
8064
8065 /* check if a "use_backend" rule matches */
8066 if (!found) {
8067 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008068 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008069 found = 1;
8070 break;
8071 }
8072 }
8073 }
8074
Willy Tarreaufbb78422011-06-05 15:38:35 +02008075 /* now we've checked all possible ways to reference a backend
8076 * from a frontend.
8077 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008078 if (!found)
8079 continue;
8080 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008081 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008082 /* we have the sum of the maxconns in <total>. We only
8083 * keep 10% of that sum to set the default fullconn, with
8084 * a hard minimum of 1 (to avoid a divide by zero).
8085 */
8086 curproxy->fullconn = (total + 9) / 10;
8087 if (!curproxy->fullconn)
8088 curproxy->fullconn = 1;
8089 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008090 }
8091
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008092 /*
8093 * Recount currently required checks.
8094 */
8095
8096 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8097 int optnum;
8098
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008099 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8100 if (curproxy->options & cfg_opts[optnum].val)
8101 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008102
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008103 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8104 if (curproxy->options2 & cfg_opts2[optnum].val)
8105 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008106 }
8107
Willy Tarreau0fca4832015-05-01 19:12:05 +02008108 /* compute the required process bindings for the peers */
8109 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8110 if (curproxy->table.peers.p)
8111 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8112
Willy Tarreau122541c2011-09-07 21:24:49 +02008113 if (peers) {
8114 struct peers *curpeers = peers, **last;
8115 struct peer *p, *pb;
8116
Willy Tarreau1e273012015-05-01 19:15:17 +02008117 /* Remove all peers sections which don't have a valid listener,
8118 * which are not used by any table, or which are bound to more
8119 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008120 */
8121 last = &peers;
8122 while (*last) {
8123 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008124
8125 if (curpeers->state == PR_STSTOPPED) {
8126 /* the "disabled" keyword was present */
8127 if (curpeers->peers_fe)
8128 stop_proxy(curpeers->peers_fe);
8129 curpeers->peers_fe = NULL;
8130 }
8131 else if (!curpeers->peers_fe) {
8132 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8133 curpeers->id, localpeer);
8134 }
Willy Tarreau1e273012015-05-01 19:15:17 +02008135 else if (popcount(curpeers->peers_fe->bind_proc) != 1) {
8136 /* either it's totally stopped or too much used */
8137 if (curpeers->peers_fe->bind_proc) {
8138 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008139 "running in different processes (%d different ones). "
8140 "Check global.nbproc and all tables' bind-process "
8141 "settings.\n", curpeers->id, popcount(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008142 cfgerr++;
8143 }
8144 stop_proxy(curpeers->peers_fe);
8145 curpeers->peers_fe = NULL;
8146 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008147 else {
Willy Tarreau122541c2011-09-07 21:24:49 +02008148 last = &curpeers->next;
8149 continue;
8150 }
8151
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008152 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008153 p = curpeers->remote;
8154 while (p) {
8155 pb = p->next;
8156 free(p->id);
8157 free(p);
8158 p = pb;
8159 }
8160
8161 /* Destroy and unlink this curpeers section.
8162 * Note: curpeers is backed up into *last.
8163 */
8164 free(curpeers->id);
8165 curpeers = curpeers->next;
8166 free(*last);
8167 *last = curpeers;
8168 }
8169 }
8170
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008171 /* initialize stick-tables on backend capable proxies. This must not
8172 * be done earlier because the data size may be discovered while parsing
8173 * other proxies.
8174 */
8175 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8176 if (curproxy->state == PR_STSTOPPED)
8177 continue;
8178
8179 if (!stktable_init(&curproxy->table)) {
8180 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8181 cfgerr++;
8182 }
8183 }
8184
Simon Horman0d16a402015-01-30 11:22:58 +09008185 if (mailers) {
8186 struct mailers *curmailers = mailers, **last;
8187 struct mailer *m, *mb;
8188
8189 /* Remove all mailers sections which don't have a valid listener.
8190 * This can happen when a mailers section is never referenced.
8191 */
8192 last = &mailers;
8193 while (*last) {
8194 curmailers = *last;
8195 if (curmailers->users) {
8196 last = &curmailers->next;
8197 continue;
8198 }
8199
8200 Warning("Removing incomplete section 'mailers %s'.\n",
8201 curmailers->id);
8202
8203 m = curmailers->mailer_list;
8204 while (m) {
8205 mb = m->next;
8206 free(m->id);
8207 free(m);
8208 m = mb;
8209 }
8210
8211 /* Destroy and unlink this curmailers section.
8212 * Note: curmailers is backed up into *last.
8213 */
8214 free(curmailers->id);
8215 curmailers = curmailers->next;
8216 free(*last);
8217 *last = curmailers;
8218 }
8219 }
8220
Willy Tarreau34eb6712011-10-24 18:15:04 +02008221 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008222 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008223 MEM_F_SHARED);
8224
Willy Tarreaubb925012009-07-23 13:36:36 +02008225 if (cfgerr > 0)
8226 err_code |= ERR_ALERT | ERR_FATAL;
8227 out:
8228 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008229}
8230
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008231/*
8232 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8233 * parsing sessions.
8234 */
8235void cfg_register_keywords(struct cfg_kw_list *kwl)
8236{
8237 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8238}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008239
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008240/*
8241 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8242 */
8243void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8244{
8245 LIST_DEL(&kwl->list);
8246 LIST_INIT(&kwl->list);
8247}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008248
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008249/* this function register new section in the haproxy configuration file.
8250 * <section_name> is the name of this new section and <section_parser>
8251 * is the called parser. If two section declaration have the same name,
8252 * only the first declared is used.
8253 */
8254int cfg_register_section(char *section_name,
8255 int (*section_parser)(const char *, int, char **, int))
8256{
8257 struct cfg_section *cs;
8258
8259 cs = calloc(1, sizeof(*cs));
8260 if (!cs) {
8261 Alert("register section '%s': out of memory.\n", section_name);
8262 return 0;
8263 }
8264
8265 cs->section_name = section_name;
8266 cs->section_parser = section_parser;
8267
8268 LIST_ADDQ(&sections, &cs->list);
8269
8270 return 1;
8271}
8272
Willy Tarreaubaaee002006-06-26 02:48:02 +02008273/*
8274 * Local variables:
8275 * c-indent-level: 8
8276 * c-basic-offset: 8
8277 * End:
8278 */