blob: d4fac8cdf9ef7a5e0a592f7c3315fab33f9a8a37 [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 Tarreau7cbc9152014-03-15 08:17:08 +01002117 struct ebpt_node *node;
2118
Willy Tarreaubaaee002006-06-26 02:48:02 +02002119 if (!*args[1]) {
2120 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2121 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2122 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002123 err_code |= ERR_ALERT | ERR_ABORT;
2124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002125 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002126
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002127 err = invalid_char(args[1]);
2128 if (err) {
2129 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2130 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002131 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002132 }
2133
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002134 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
2135 curproxy = container_of(node, struct proxy, conf.by_name);
2136
2137 if (strcmp(curproxy->id, args[1]) != 0)
2138 break;
2139
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002140 /*
2141 * If there are two proxies with the same name only following
2142 * combinations are allowed:
2143 *
2144 * listen backend frontend ruleset
2145 * listen - - - -
2146 * backend - - OK -
2147 * frontend - OK - -
2148 * ruleset - - - -
2149 */
2150
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002151 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
2152 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002153 Alert("Parsing [%s:%d]: %s '%s' has the same name as another %s declared at %s:%d.\n",
Willy Tarreau092549f2009-10-04 21:11:42 +02002154 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2155 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002156 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002157 }
2158 }
2159
Willy Tarreaubaaee002006-06-26 02:48:02 +02002160 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2161 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002162 err_code |= ERR_ALERT | ERR_ABORT;
2163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002164 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002165
Willy Tarreau97cb7802010-01-03 20:23:58 +01002166 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002167 curproxy->next = proxy;
2168 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002169 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2170 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002171 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002172 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002173 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002174 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002175
2176 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002177 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002178 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02002179
Willy Tarreau4348fad2012-09-20 16:48:07 +02002180 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2181
Willy Tarreau902636f2013-03-10 19:44:48 +01002182 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2183 if (errmsg && *errmsg) {
2184 indent_msg(&errmsg, 2);
2185 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002186 }
2187 else
2188 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2189 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002190 err_code |= ERR_FATAL;
2191 goto out;
2192 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002193
Willy Tarreau4348fad2012-09-20 16:48:07 +02002194 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002195 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002197 }
2198
2199 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002200 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002201 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002202
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002205 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002206 curproxy->no_options = defproxy.no_options;
2207 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002208 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002209 curproxy->except_net = defproxy.except_net;
2210 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002211 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002212 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002213
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002214 if (defproxy.fwdfor_hdr_len) {
2215 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2216 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2217 }
2218
Willy Tarreaub86db342009-11-30 11:50:16 +01002219 if (defproxy.orgto_hdr_len) {
2220 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2221 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2222 }
2223
Mark Lamourinec2247f02012-01-04 13:02:01 -05002224 if (defproxy.server_id_hdr_len) {
2225 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2226 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2227 }
2228
Willy Tarreau977b8e42006-12-29 14:19:17 +01002229 if (curproxy->cap & PR_CAP_FE) {
2230 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002231 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002232 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002233
2234 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002235 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2236 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002237
2238 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240
Willy Tarreau977b8e42006-12-29 14:19:17 +01002241 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002242 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002243 curproxy->fullconn = defproxy.fullconn;
2244 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002245 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002246 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002247
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002248 if (defproxy.check_req) {
2249 curproxy->check_req = calloc(1, defproxy.check_len);
2250 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2251 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002252 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002253
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002254 if (defproxy.expect_str) {
2255 curproxy->expect_str = strdup(defproxy.expect_str);
2256 if (defproxy.expect_regex) {
2257 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002258 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2259 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002260 }
2261 }
2262
Willy Tarreau67402132012-05-31 20:40:20 +02002263 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002264 if (defproxy.cookie_name)
2265 curproxy->cookie_name = strdup(defproxy.cookie_name);
2266 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002267 if (defproxy.cookie_domain)
2268 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002269
Willy Tarreau31936852010-10-06 16:59:56 +02002270 if (defproxy.cookie_maxidle)
2271 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2272
2273 if (defproxy.cookie_maxlife)
2274 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2275
Emeric Brun647caf12009-06-30 17:57:00 +02002276 if (defproxy.rdp_cookie_name)
2277 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2278 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2279
Willy Tarreau01732802007-11-01 22:48:15 +01002280 if (defproxy.url_param_name)
2281 curproxy->url_param_name = strdup(defproxy.url_param_name);
2282 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002283
Benoitaffb4812009-03-25 13:02:10 +01002284 if (defproxy.hh_name)
2285 curproxy->hh_name = strdup(defproxy.hh_name);
2286 curproxy->hh_len = defproxy.hh_len;
2287 curproxy->hh_match_domain = defproxy.hh_match_domain;
2288
Willy Tarreauef9a3602012-12-08 22:29:20 +01002289 if (defproxy.conn_src.iface_name)
2290 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2291 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002292 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002293#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002294 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002295#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002296 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002297
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002298 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002299 if (defproxy.capture_name)
2300 curproxy->capture_name = strdup(defproxy.capture_name);
2301 curproxy->capture_namelen = defproxy.capture_namelen;
2302 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002303 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002304
Willy Tarreau977b8e42006-12-29 14:19:17 +01002305 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002306 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002307 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002308 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002309 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002310 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002311 curproxy->mon_net = defproxy.mon_net;
2312 curproxy->mon_mask = defproxy.mon_mask;
2313 if (defproxy.monitor_uri)
2314 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2315 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002316 if (defproxy.defbe.name)
2317 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002318
2319 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002320 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2321 if (curproxy->conf.logformat_string &&
2322 curproxy->conf.logformat_string != default_http_log_format &&
2323 curproxy->conf.logformat_string != default_tcp_log_format &&
2324 curproxy->conf.logformat_string != clf_http_log_format)
2325 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2326
2327 if (defproxy.conf.lfs_file) {
2328 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2329 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2330 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002331 }
2332
2333 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002334 curproxy->timeout.connect = defproxy.timeout.connect;
2335 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002336 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002337 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002338 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002339 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002340 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002341 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002342 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002343 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002344 }
2345
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002347 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002348
2349 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002350 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002351 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002352 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002353 LIST_INIT(&node->list);
2354 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2355 }
2356
Willy Tarreau62a61232013-04-12 18:13:46 +02002357 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2358 if (curproxy->conf.uniqueid_format_string)
2359 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2360
Willy Tarreau094af4e2015-01-07 15:03:42 +01002361 if (defproxy.log_tag)
2362 curproxy->log_tag = strdup(defproxy.log_tag);
2363
Willy Tarreau62a61232013-04-12 18:13:46 +02002364 if (defproxy.conf.uif_file) {
2365 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2366 curproxy->conf.uif_line = defproxy.conf.uif_line;
2367 }
William Lallemanda73203e2012-03-12 12:48:57 +01002368
2369 /* copy default header unique id */
2370 if (defproxy.header_unique_id)
2371 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2372
William Lallemand82fe75c2012-10-23 10:25:10 +02002373 /* default compression options */
2374 if (defproxy.comp != NULL) {
2375 curproxy->comp = calloc(1, sizeof(struct comp));
2376 curproxy->comp->algos = defproxy.comp->algos;
2377 curproxy->comp->types = defproxy.comp->types;
2378 }
2379
Willy Tarreaubaaee002006-06-26 02:48:02 +02002380 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002381 curproxy->conf.used_listener_id = EB_ROOT;
2382 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002383
Simon Horman98637e52014-06-20 12:30:16 +09002384 if (defproxy.check_path)
2385 curproxy->check_path = strdup(defproxy.check_path);
2386 if (defproxy.check_command)
2387 curproxy->check_command = strdup(defproxy.check_command);
2388
Simon Horman9dc49962015-01-30 11:22:59 +09002389 if (defproxy.email_alert.mailers.name)
2390 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2391 if (defproxy.email_alert.from)
2392 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2393 if (defproxy.email_alert.to)
2394 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2395 if (defproxy.email_alert.myhostname)
2396 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002397 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002398
Willy Tarreau93893792009-07-23 13:19:11 +02002399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 }
2401 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2402 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002403 /* FIXME-20070101: we should do this too at the end of the
2404 * config parsing to free all default values.
2405 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002406 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002407 free(defproxy.check_command);
2408 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002409 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002410 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002411 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002412 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002413 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002414 free(defproxy.capture_name);
2415 free(defproxy.monitor_uri);
2416 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002417 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002418 free(defproxy.fwdfor_hdr_name);
2419 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002420 free(defproxy.orgto_hdr_name);
2421 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002422 free(defproxy.server_id_hdr_name);
2423 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002424 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002425 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002426 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002427 free(defproxy.expect_regex);
2428 defproxy.expect_regex = NULL;
2429 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002430
Willy Tarreau62a61232013-04-12 18:13:46 +02002431 if (defproxy.conf.logformat_string != default_http_log_format &&
2432 defproxy.conf.logformat_string != default_tcp_log_format &&
2433 defproxy.conf.logformat_string != clf_http_log_format)
2434 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002435
Willy Tarreau62a61232013-04-12 18:13:46 +02002436 free(defproxy.conf.uniqueid_format_string);
2437 free(defproxy.conf.lfs_file);
2438 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002439 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002440 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002441
Willy Tarreaua534fea2008-08-03 12:19:50 +02002442 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002443 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002444
Willy Tarreaubaaee002006-06-26 02:48:02 +02002445 /* we cannot free uri_auth because it might already be used */
2446 init_default_instance();
2447 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002448 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2449 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002450 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002451 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452 }
2453 else if (curproxy == NULL) {
2454 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
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 Tarreaua4312fa2013-04-02 16:34:32 +02002458
2459 /* update the current file and line being parsed */
2460 curproxy->conf.args.file = curproxy->conf.file;
2461 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002462
2463 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002464 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2465 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2466 if (err_code & ERR_FATAL)
2467 goto out;
2468 }
2469 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002470 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002471 int cur_arg;
2472
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 if (curproxy == &defproxy) {
2474 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002478 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002479 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002480
Willy Tarreau24709282013-03-10 21:32:12 +01002481 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002482 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002483 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002484 err_code |= ERR_ALERT | ERR_FATAL;
2485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002486 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002487
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002488 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002489
2490 /* use default settings for unix sockets */
2491 bind_conf->ux.uid = global.unix_bind.ux.uid;
2492 bind_conf->ux.gid = global.unix_bind.ux.gid;
2493 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002494
2495 /* NOTE: the following line might create several listeners if there
2496 * are comma-separated IPs or port ranges. So all further processing
2497 * will have to be applied to all listeners created after last_listen.
2498 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002499 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2500 if (errmsg && *errmsg) {
2501 indent_msg(&errmsg, 2);
2502 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002503 }
2504 else
2505 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2506 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002507 err_code |= ERR_ALERT | ERR_FATAL;
2508 goto out;
2509 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002510
Willy Tarreau4348fad2012-09-20 16:48:07 +02002511 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2512 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002513 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002514 }
2515
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002516 cur_arg = 2;
2517 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002518 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002519 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002520 char *err;
2521
Willy Tarreau26982662012-09-12 23:17:10 +02002522 kw = bind_find_kw(args[cur_arg]);
2523 if (kw) {
2524 char *err = NULL;
2525 int code;
2526
2527 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002528 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2529 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002530 cur_arg += 1 + kw->skip ;
2531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
2533 }
2534
Willy Tarreau4348fad2012-09-20 16:48:07 +02002535 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002536 err_code |= code;
2537
2538 if (code) {
2539 if (err && *err) {
2540 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002541 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002542 }
2543 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002544 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2545 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002546 if (code & ERR_FATAL) {
2547 free(err);
2548 cur_arg += 1 + kw->skip;
2549 goto out;
2550 }
2551 }
2552 free(err);
2553 cur_arg += 1 + kw->skip;
2554 continue;
2555 }
2556
Willy Tarreau8638f482012-09-18 18:01:17 +02002557 err = NULL;
2558 if (!bind_dumped) {
2559 bind_dump_kws(&err);
2560 indent_msg(&err, 4);
2561 bind_dumped = 1;
2562 }
2563
2564 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2565 file, linenum, args[0], args[1], args[cur_arg],
2566 err ? " Registered keywords :" : "", err ? err : "");
2567 free(err);
2568
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_ALERT | ERR_FATAL;
2570 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002571 }
Willy Tarreau93893792009-07-23 13:19:11 +02002572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002573 }
2574 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002575 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2577 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002578 err_code |= ERR_ALERT | ERR_FATAL;
2579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002581 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002582 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002583
Willy Tarreaubaaee002006-06-26 02:48:02 +02002584 /* flush useless bits */
2585 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002588 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002589 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002590 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002591
Willy Tarreau1c47f852006-07-09 08:22:27 +02002592 if (!*args[1]) {
2593 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2594 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002597 }
2598
Willy Tarreaua534fea2008-08-03 12:19:50 +02002599 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002600 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002601 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002602 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002603 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2604
Willy Tarreau93893792009-07-23 13:19:11 +02002605 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2608 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2609 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2610 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2611 else {
2612 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002613 err_code |= ERR_ALERT | ERR_FATAL;
2614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002615 }
2616 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002617 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002618 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002619
2620 if (curproxy == &defproxy) {
2621 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2622 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002623 err_code |= ERR_ALERT | ERR_FATAL;
2624 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002625 }
2626
2627 if (!*args[1]) {
2628 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2629 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002632 }
2633
2634 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002635 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002636
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002637 if (curproxy->uuid <= 0) {
2638 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002639 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002640 err_code |= ERR_ALERT | ERR_FATAL;
2641 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002642 }
2643
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002644 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2645 if (node) {
2646 struct proxy *target = container_of(node, struct proxy, conf.id);
2647 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2648 file, linenum, proxy_type_str(curproxy), curproxy->id,
2649 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
2652 }
2653 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002654 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002655 else if (!strcmp(args[0], "description")) {
2656 int i, len=0;
2657 char *d;
2658
Cyril Bonté99ed3272010-01-24 23:29:44 +01002659 if (curproxy == &defproxy) {
2660 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2661 file, linenum, args[0]);
2662 err_code |= ERR_ALERT | ERR_FATAL;
2663 goto out;
2664 }
2665
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002666 if (!*args[1]) {
2667 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2668 file, linenum, args[0]);
2669 return -1;
2670 }
2671
Willy Tarreau348acfe2014-04-14 15:00:39 +02002672 for (i = 1; *args[i]; i++)
2673 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002674
2675 d = (char *)calloc(1, len);
2676 curproxy->desc = d;
2677
Willy Tarreau348acfe2014-04-14 15:00:39 +02002678 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2679 for (i = 2; *args[i]; i++)
2680 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002681
2682 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002683 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2684 curproxy->state = PR_STSTOPPED;
2685 }
2686 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2687 curproxy->state = PR_STNEW;
2688 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002689 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2690 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002691 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002692
2693 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002694 unsigned int low, high;
2695
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002696 if (strcmp(args[cur_arg], "all") == 0) {
2697 set = 0;
2698 break;
2699 }
2700 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002701 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002702 }
2703 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002704 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002705 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002706 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002707 char *dash = strchr(args[cur_arg], '-');
2708
2709 low = high = str2uic(args[cur_arg]);
2710 if (dash)
2711 high = str2uic(dash + 1);
2712
2713 if (high < low) {
2714 unsigned int swap = low;
2715 low = high;
2716 high = swap;
2717 }
2718
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002719 if (low < 1 || high > LONGBITS) {
2720 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2721 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002722 err_code |= ERR_ALERT | ERR_FATAL;
2723 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002724 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002725 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002726 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002727 }
2728 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002729 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2730 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002731 err_code |= ERR_ALERT | ERR_FATAL;
2732 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002733 }
2734 cur_arg++;
2735 }
2736 curproxy->bind_proc = set;
2737 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002738 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002739 if (curproxy == &defproxy) {
2740 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002743 }
2744
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002745 err = invalid_char(args[1]);
2746 if (err) {
2747 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2748 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002749 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002750 }
2751
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002752 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002753 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2754 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002755 err_code |= ERR_ALERT | ERR_FATAL;
2756 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002757 }
2758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2760 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002761
Willy Tarreau977b8e42006-12-29 14:19:17 +01002762 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002763 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002764
Willy Tarreaubaaee002006-06-26 02:48:02 +02002765 if (*(args[1]) == 0) {
2766 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2767 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002770 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002771
Willy Tarreau67402132012-05-31 20:40:20 +02002772 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002773 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002774 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002775 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002776 curproxy->cookie_name = strdup(args[1]);
2777 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002778
Willy Tarreaubaaee002006-06-26 02:48:02 +02002779 cur_arg = 2;
2780 while (*(args[cur_arg])) {
2781 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002782 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002783 }
2784 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002785 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002786 }
2787 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002788 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002789 }
2790 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002791 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002792 }
2793 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002794 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002795 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002796 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002797 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002798 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002799 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002800 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002801 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002802 else if (!strcmp(args[cur_arg], "httponly")) {
2803 curproxy->ck_opts |= PR_CK_HTTPONLY;
2804 }
2805 else if (!strcmp(args[cur_arg], "secure")) {
2806 curproxy->ck_opts |= PR_CK_SECURE;
2807 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002808 else if (!strcmp(args[cur_arg], "domain")) {
2809 if (!*args[cur_arg + 1]) {
2810 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2811 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002812 err_code |= ERR_ALERT | ERR_FATAL;
2813 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002814 }
2815
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002816 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002817 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002818 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2819 " dots nor does not start with a dot."
2820 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002821 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002822 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002823 }
2824
2825 err = invalid_domainchar(args[cur_arg + 1]);
2826 if (err) {
2827 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2828 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002829 err_code |= ERR_ALERT | ERR_FATAL;
2830 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002831 }
2832
Willy Tarreau68a897b2009-12-03 23:28:34 +01002833 if (!curproxy->cookie_domain) {
2834 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2835 } else {
2836 /* one domain was already specified, add another one by
2837 * building the string which will be returned along with
2838 * the cookie.
2839 */
2840 char *new_ptr;
2841 int new_len = strlen(curproxy->cookie_domain) +
2842 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2843 new_ptr = malloc(new_len);
2844 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2845 free(curproxy->cookie_domain);
2846 curproxy->cookie_domain = new_ptr;
2847 }
Willy Tarreau31936852010-10-06 16:59:56 +02002848 cur_arg++;
2849 }
2850 else if (!strcmp(args[cur_arg], "maxidle")) {
2851 unsigned int maxidle;
2852 const char *res;
2853
2854 if (!*args[cur_arg + 1]) {
2855 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2856 file, linenum, args[cur_arg]);
2857 err_code |= ERR_ALERT | ERR_FATAL;
2858 goto out;
2859 }
2860
2861 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2862 if (res) {
2863 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2864 file, linenum, *res, args[cur_arg]);
2865 err_code |= ERR_ALERT | ERR_FATAL;
2866 goto out;
2867 }
2868 curproxy->cookie_maxidle = maxidle;
2869 cur_arg++;
2870 }
2871 else if (!strcmp(args[cur_arg], "maxlife")) {
2872 unsigned int maxlife;
2873 const char *res;
2874
2875 if (!*args[cur_arg + 1]) {
2876 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2877 file, linenum, args[cur_arg]);
2878 err_code |= ERR_ALERT | ERR_FATAL;
2879 goto out;
2880 }
2881
2882 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2883 if (res) {
2884 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2885 file, linenum, *res, args[cur_arg]);
2886 err_code |= ERR_ALERT | ERR_FATAL;
2887 goto out;
2888 }
2889 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002890 cur_arg++;
2891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002892 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002893 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 +02002894 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002895 err_code |= ERR_ALERT | ERR_FATAL;
2896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 }
2898 cur_arg++;
2899 }
Willy Tarreau67402132012-05-31 20:40:20 +02002900 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002901 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2902 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002903 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002904 }
2905
Willy Tarreau67402132012-05-31 20:40:20 +02002906 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002907 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2908 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002909 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002910 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002911
Willy Tarreau67402132012-05-31 20:40:20 +02002912 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002913 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2914 file, linenum);
2915 err_code |= ERR_ALERT | ERR_FATAL;
2916 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002917 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09002918 else if (!strcmp(args[0], "email-alert")) {
2919 if (*(args[1]) == 0) {
2920 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2921 file, linenum, args[0]);
2922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
2924 }
2925
2926 if (!strcmp(args[1], "from")) {
2927 if (*(args[1]) == 0) {
2928 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2929 file, linenum, args[1]);
2930 err_code |= ERR_ALERT | ERR_FATAL;
2931 goto out;
2932 }
2933 free(curproxy->email_alert.from);
2934 curproxy->email_alert.from = strdup(args[2]);
2935 }
2936 else if (!strcmp(args[1], "mailers")) {
2937 if (*(args[1]) == 0) {
2938 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2939 file, linenum, args[1]);
2940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
2942 }
2943 free(curproxy->email_alert.mailers.name);
2944 curproxy->email_alert.mailers.name = strdup(args[2]);
2945 }
2946 else if (!strcmp(args[1], "myhostname")) {
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.myhostname);
2954 curproxy->email_alert.myhostname = strdup(args[2]);
2955 }
Simon Horman64e34162015-02-06 11:11:57 +09002956 else if (!strcmp(args[1], "level")) {
2957 curproxy->email_alert.level = get_log_level(args[2]);
2958 if (curproxy->email_alert.level < 0) {
2959 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
2960 file, linenum, args[1], args[2]);
2961 err_code |= ERR_ALERT | ERR_FATAL;
2962 goto out;
2963 }
2964 }
Simon Horman9dc49962015-01-30 11:22:59 +09002965 else if (!strcmp(args[1], "to")) {
2966 if (*(args[1]) == 0) {
2967 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2968 file, linenum, args[1]);
2969 err_code |= ERR_ALERT | ERR_FATAL;
2970 goto out;
2971 }
2972 free(curproxy->email_alert.to);
2973 curproxy->email_alert.to = strdup(args[2]);
2974 }
2975 else {
2976 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
2977 file, linenum, args[1]);
2978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
2980 }
Simon Horman64e34162015-02-06 11:11:57 +09002981 /* Indicate that the email_alert is at least partially configured */
2982 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09002983 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09002984 else if (!strcmp(args[0], "external-check")) {
2985 if (*(args[1]) == 0) {
2986 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2987 file, linenum, args[0]);
2988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
2990 }
2991
2992 if (!strcmp(args[1], "command")) {
2993 if (*(args[1]) == 0) {
2994 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2995 file, linenum, args[1]);
2996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
2998 }
2999 free(curproxy->check_command);
3000 curproxy->check_command = strdup(args[2]);
3001 }
3002 else if (!strcmp(args[1], "path")) {
3003 if (*(args[1]) == 0) {
3004 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3005 file, linenum, args[1]);
3006 err_code |= ERR_ALERT | ERR_FATAL;
3007 goto out;
3008 }
3009 free(curproxy->check_path);
3010 curproxy->check_path = strdup(args[2]);
3011 }
3012 else {
3013 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3014 file, linenum, args[1]);
3015 err_code |= ERR_ALERT | ERR_FATAL;
3016 goto out;
3017 }
3018 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003019 else if (!strcmp(args[0], "persist")) { /* persist */
3020 if (*(args[1]) == 0) {
3021 Alert("parsing [%s:%d] : missing persist method.\n",
3022 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003023 err_code |= ERR_ALERT | ERR_FATAL;
3024 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003025 }
3026
3027 if (!strncmp(args[1], "rdp-cookie", 10)) {
3028 curproxy->options2 |= PR_O2_RDPC_PRST;
3029
Emeric Brunb982a3d2010-01-04 15:45:53 +01003030 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003031 const char *beg, *end;
3032
3033 beg = args[1] + 11;
3034 end = strchr(beg, ')');
3035
3036 if (!end || end == beg) {
3037 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3038 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003041 }
3042
3043 free(curproxy->rdp_cookie_name);
3044 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3045 curproxy->rdp_cookie_len = end-beg;
3046 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003047 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003048 free(curproxy->rdp_cookie_name);
3049 curproxy->rdp_cookie_name = strdup("msts");
3050 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3051 }
3052 else { /* syntax */
3053 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3054 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003057 }
3058 }
3059 else {
3060 Alert("parsing [%s:%d] : unknown persist method.\n",
3061 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003062 err_code |= ERR_ALERT | ERR_FATAL;
3063 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003064 }
3065 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003067 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003068
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003069 if (curproxy == &defproxy) {
3070 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
3073 }
3074
Willy Tarreau977b8e42006-12-29 14:19:17 +01003075 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003076 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003077
Willy Tarreaubaaee002006-06-26 02:48:02 +02003078 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003079 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 }
3084 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003085 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 curproxy->appsession_name = strdup(args[1]);
3087 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3088 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003089 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3090 if (err) {
3091 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3092 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003093 err_code |= ERR_ALERT | ERR_FATAL;
3094 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003095 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003096 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003097
Willy Tarreau51041c72007-09-09 21:56:53 +02003098 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3099 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003100 err_code |= ERR_ALERT | ERR_ABORT;
3101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003102 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003103
3104 cur_arg = 6;
3105 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003106 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3107 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003108 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003109 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003110 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003111 } else if (!strcmp(args[cur_arg], "prefix")) {
3112 curproxy->options2 |= PR_O2_AS_PFX;
3113 } else if (!strcmp(args[cur_arg], "mode")) {
3114 if (!*args[cur_arg + 1]) {
3115 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3116 file, linenum, args[0], args[cur_arg]);
3117 err_code |= ERR_ALERT | ERR_FATAL;
3118 goto out;
3119 }
3120
3121 cur_arg++;
3122 if (!strcmp(args[cur_arg], "query-string")) {
3123 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3124 curproxy->options2 |= PR_O2_AS_M_QS;
3125 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3126 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3127 curproxy->options2 |= PR_O2_AS_M_PP;
3128 } else {
3129 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3130 err_code |= ERR_ALERT | ERR_FATAL;
3131 goto out;
3132 }
3133 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003134 cur_arg++;
3135 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136 } /* Url App Session */
3137 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003138 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003139 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003140
Willy Tarreaubaaee002006-06-26 02:48:02 +02003141 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003142 if (curproxy == &defproxy) {
3143 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3144 err_code |= ERR_ALERT | ERR_FATAL;
3145 goto out;
3146 }
3147
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 if (*(args[4]) == 0) {
3149 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3150 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003151 err_code |= ERR_ALERT | ERR_FATAL;
3152 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003153 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003154 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 curproxy->capture_name = strdup(args[2]);
3156 curproxy->capture_namelen = strlen(curproxy->capture_name);
3157 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 curproxy->to_log |= LW_COOKIE;
3159 }
3160 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3161 struct cap_hdr *hdr;
3162
3163 if (curproxy == &defproxy) {
3164 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 +02003165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167 }
3168
3169 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3170 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3171 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 hdr = calloc(sizeof(struct cap_hdr), 1);
3177 hdr->next = curproxy->req_cap;
3178 hdr->name = strdup(args[3]);
3179 hdr->namelen = strlen(args[3]);
3180 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003181 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003182 hdr->index = curproxy->nb_req_cap++;
3183 curproxy->req_cap = hdr;
3184 curproxy->to_log |= LW_REQHDR;
3185 }
3186 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3187 struct cap_hdr *hdr;
3188
3189 if (curproxy == &defproxy) {
3190 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 +02003191 err_code |= ERR_ALERT | ERR_FATAL;
3192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003193 }
3194
3195 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3196 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3197 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003198 err_code |= ERR_ALERT | ERR_FATAL;
3199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003200 }
3201 hdr = calloc(sizeof(struct cap_hdr), 1);
3202 hdr->next = curproxy->rsp_cap;
3203 hdr->name = strdup(args[3]);
3204 hdr->namelen = strlen(args[3]);
3205 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003206 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 hdr->index = curproxy->nb_rsp_cap++;
3208 curproxy->rsp_cap = hdr;
3209 curproxy->to_log |= LW_RSPHDR;
3210 }
3211 else {
3212 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3213 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003214 err_code |= ERR_ALERT | ERR_FATAL;
3215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003216 }
3217 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003218 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003219 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003220 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003221
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 if (*(args[1]) == 0) {
3223 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3224 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003225 err_code |= ERR_ALERT | ERR_FATAL;
3226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 }
3228 curproxy->conn_retries = atol(args[1]);
3229 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003230 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003231 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003232
3233 if (curproxy == &defproxy) {
3234 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3235 err_code |= ERR_ALERT | ERR_FATAL;
3236 goto out;
3237 }
3238
Willy Tarreau20b0de52012-12-24 15:45:22 +01003239 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3240 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3241 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3242 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003243 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003244 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3245 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 +01003246 file, linenum, args[0]);
3247 err_code |= ERR_WARN;
3248 }
3249
Willy Tarreauff011f22011-01-06 17:51:27 +01003250 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003251
Willy Tarreauff011f22011-01-06 17:51:27 +01003252 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003253 err_code |= ERR_ALERT | ERR_ABORT;
3254 goto out;
3255 }
3256
Willy Tarreau5002f572014-04-23 01:32:02 +02003257 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003258 err_code |= warnif_cond_conflicts(rule->cond,
3259 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3260 file, linenum);
3261
Willy Tarreauff011f22011-01-06 17:51:27 +01003262 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003263 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003264 else if (!strcmp(args[0], "http-response")) { /* response access control */
3265 struct http_res_rule *rule;
3266
3267 if (curproxy == &defproxy) {
3268 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3269 err_code |= ERR_ALERT | ERR_FATAL;
3270 goto out;
3271 }
3272
3273 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3274 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3275 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3276 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3277 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3278 file, linenum, args[0]);
3279 err_code |= ERR_WARN;
3280 }
3281
3282 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3283
3284 if (!rule) {
3285 err_code |= ERR_ALERT | ERR_ABORT;
3286 goto out;
3287 }
3288
3289 err_code |= warnif_cond_conflicts(rule->cond,
3290 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3291 file, linenum);
3292
3293 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3294 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003295 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3296 /* set the header name and length into the proxy structure */
3297 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3298 err_code |= ERR_WARN;
3299
3300 if (!*args[1]) {
3301 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3302 file, linenum, args[0]);
3303 err_code |= ERR_ALERT | ERR_FATAL;
3304 goto out;
3305 }
3306
3307 /* set the desired header name */
3308 free(curproxy->server_id_hdr_name);
3309 curproxy->server_id_hdr_name = strdup(args[1]);
3310 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3311 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003312 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003313 struct http_req_rule *rule;
3314
Willy Tarreaub099aca2008-10-12 17:26:37 +02003315 if (curproxy == &defproxy) {
3316 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003317 err_code |= ERR_ALERT | ERR_FATAL;
3318 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003319 }
3320
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003321 /* emulate "block" using "http-request block". Since these rules are supposed to
3322 * be processed before all http-request rules, we put them into their own list
3323 * and will insert them at the end.
3324 */
3325 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3326 if (!rule) {
3327 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003328 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003329 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003330 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3331 err_code |= warnif_cond_conflicts(rule->cond,
3332 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3333 file, linenum);
3334 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003335
3336 if (!already_warned(WARN_BLOCK_DEPRECATED))
3337 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]);
3338
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003339 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003340 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003341 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003342
Cyril Bonté99ed3272010-01-24 23:29:44 +01003343 if (curproxy == &defproxy) {
3344 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3345 err_code |= ERR_ALERT | ERR_FATAL;
3346 goto out;
3347 }
3348
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003349 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003350 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3351 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003352 err_code |= ERR_ALERT | ERR_FATAL;
3353 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003354 }
3355
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003356 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003357 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003358 err_code |= warnif_cond_conflicts(rule->cond,
3359 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3360 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003361 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003362 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003363 struct switching_rule *rule;
3364
Willy Tarreaub099aca2008-10-12 17:26:37 +02003365 if (curproxy == &defproxy) {
3366 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003367 err_code |= ERR_ALERT | ERR_FATAL;
3368 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003369 }
3370
Willy Tarreau55ea7572007-06-17 19:56:27 +02003371 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003372 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003373
3374 if (*(args[1]) == 0) {
3375 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003376 err_code |= ERR_ALERT | ERR_FATAL;
3377 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003378 }
3379
Willy Tarreauf51658d2014-04-23 01:21:56 +02003380 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3381 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3382 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3383 file, linenum, errmsg);
3384 err_code |= ERR_ALERT | ERR_FATAL;
3385 goto out;
3386 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003387
Willy Tarreauf51658d2014-04-23 01:21:56 +02003388 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003389 }
3390
3391 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3392 rule->cond = cond;
3393 rule->be.name = strdup(args[1]);
3394 LIST_INIT(&rule->list);
3395 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3396 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003397 else if (strcmp(args[0], "use-server") == 0) {
3398 struct server_rule *rule;
3399
3400 if (curproxy == &defproxy) {
3401 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3402 err_code |= ERR_ALERT | ERR_FATAL;
3403 goto out;
3404 }
3405
3406 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3407 err_code |= ERR_WARN;
3408
3409 if (*(args[1]) == 0) {
3410 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3411 err_code |= ERR_ALERT | ERR_FATAL;
3412 goto out;
3413 }
3414
3415 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3416 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3417 file, linenum, args[0]);
3418 err_code |= ERR_ALERT | ERR_FATAL;
3419 goto out;
3420 }
3421
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003422 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3423 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3424 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003425 err_code |= ERR_ALERT | ERR_FATAL;
3426 goto out;
3427 }
3428
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003429 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003430
3431 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3432 rule->cond = cond;
3433 rule->srv.name = strdup(args[1]);
3434 LIST_INIT(&rule->list);
3435 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3436 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3437 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003438 else if ((!strcmp(args[0], "force-persist")) ||
3439 (!strcmp(args[0], "ignore-persist"))) {
3440 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003441
3442 if (curproxy == &defproxy) {
3443 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3444 err_code |= ERR_ALERT | ERR_FATAL;
3445 goto out;
3446 }
3447
3448 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3449 err_code |= ERR_WARN;
3450
Willy Tarreauef6494c2010-01-28 17:12:36 +01003451 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003452 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3453 file, linenum, args[0]);
3454 err_code |= ERR_ALERT | ERR_FATAL;
3455 goto out;
3456 }
3457
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003458 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3459 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3460 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003461 err_code |= ERR_ALERT | ERR_FATAL;
3462 goto out;
3463 }
3464
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003465 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3466 * where force-persist is applied.
3467 */
3468 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003469
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003470 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003471 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003472 if (!strcmp(args[0], "force-persist")) {
3473 rule->type = PERSIST_TYPE_FORCE;
3474 } else {
3475 rule->type = PERSIST_TYPE_IGNORE;
3476 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003477 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003478 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003479 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003480 else if (!strcmp(args[0], "stick-table")) {
3481 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003482 struct proxy *other;
3483
3484 other = find_stktable(curproxy->id);
3485 if (other) {
3486 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3487 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
3490 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003491
Emeric Brun32da3c42010-09-23 18:39:19 +02003492 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003493 curproxy->table.type = (unsigned int)-1;
3494 while (*args[myidx]) {
3495 const char *err;
3496
3497 if (strcmp(args[myidx], "size") == 0) {
3498 myidx++;
3499 if (!*(args[myidx])) {
3500 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3501 file, linenum, args[myidx-1]);
3502 err_code |= ERR_ALERT | ERR_FATAL;
3503 goto out;
3504 }
3505 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3506 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3507 file, linenum, *err, args[myidx-1]);
3508 err_code |= ERR_ALERT | ERR_FATAL;
3509 goto out;
3510 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003511 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003512 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003513 else if (strcmp(args[myidx], "peers") == 0) {
3514 myidx++;
Godbach50523162013-12-11 19:48:57 +08003515 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003516 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3517 file, linenum, args[myidx-1]);
3518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
Godbach50523162013-12-11 19:48:57 +08003520 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003521 curproxy->table.peers.name = strdup(args[myidx++]);
3522 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003523 else if (strcmp(args[myidx], "expire") == 0) {
3524 myidx++;
3525 if (!*(args[myidx])) {
3526 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3527 file, linenum, args[myidx-1]);
3528 err_code |= ERR_ALERT | ERR_FATAL;
3529 goto out;
3530 }
3531 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3532 if (err) {
3533 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3534 file, linenum, *err, args[myidx-1]);
3535 err_code |= ERR_ALERT | ERR_FATAL;
3536 goto out;
3537 }
3538 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003539 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003540 }
3541 else if (strcmp(args[myidx], "nopurge") == 0) {
3542 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003543 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003544 }
3545 else if (strcmp(args[myidx], "type") == 0) {
3546 myidx++;
3547 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3548 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3549 file, linenum, args[myidx]);
3550 err_code |= ERR_ALERT | ERR_FATAL;
3551 goto out;
3552 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003553 /* myidx already points to next arg */
3554 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003555 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003556 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003557 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003558
3559 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003560 nw = args[myidx];
3561 while (*nw) {
3562 /* the "store" keyword supports a comma-separated list */
3563 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003564 sa = NULL; /* store arg */
3565 while (*nw && *nw != ',') {
3566 if (*nw == '(') {
3567 *nw = 0;
3568 sa = ++nw;
3569 while (*nw != ')') {
3570 if (!*nw) {
3571 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3572 file, linenum, args[0], cw);
3573 err_code |= ERR_ALERT | ERR_FATAL;
3574 goto out;
3575 }
3576 nw++;
3577 }
3578 *nw = '\0';
3579 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003580 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003581 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003582 if (*nw)
3583 *nw++ = '\0';
3584 type = stktable_get_data_type(cw);
3585 if (type < 0) {
3586 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3587 file, linenum, args[0], cw);
3588 err_code |= ERR_ALERT | ERR_FATAL;
3589 goto out;
3590 }
Willy Tarreauac782882010-06-20 10:41:54 +02003591
3592 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3593 switch (err) {
3594 case PE_NONE: break;
3595 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003596 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3597 file, linenum, args[0], cw);
3598 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003599 break;
3600
3601 case PE_ARG_MISSING:
3602 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3603 file, linenum, args[0], cw);
3604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
3606
3607 case PE_ARG_NOT_USED:
3608 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3609 file, linenum, args[0], cw);
3610 err_code |= ERR_ALERT | ERR_FATAL;
3611 goto out;
3612
3613 default:
3614 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3615 file, linenum, args[0], cw);
3616 err_code |= ERR_ALERT | ERR_FATAL;
3617 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003618 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003619 }
3620 myidx++;
3621 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003622 else {
3623 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3624 file, linenum, args[myidx]);
3625 err_code |= ERR_ALERT | ERR_FATAL;
3626 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003627 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003628 }
3629
3630 if (!curproxy->table.size) {
3631 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3632 file, linenum);
3633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
3635 }
3636
3637 if (curproxy->table.type == (unsigned int)-1) {
3638 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3639 file, linenum);
3640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
3642 }
3643 }
3644 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003645 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003646 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003647 int myidx = 0;
3648 const char *name = NULL;
3649 int flags;
3650
3651 if (curproxy == &defproxy) {
3652 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3653 err_code |= ERR_ALERT | ERR_FATAL;
3654 goto out;
3655 }
3656
3657 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3658 err_code |= ERR_WARN;
3659 goto out;
3660 }
3661
3662 myidx++;
3663 if ((strcmp(args[myidx], "store") == 0) ||
3664 (strcmp(args[myidx], "store-request") == 0)) {
3665 myidx++;
3666 flags = STK_IS_STORE;
3667 }
3668 else if (strcmp(args[myidx], "store-response") == 0) {
3669 myidx++;
3670 flags = STK_IS_STORE | STK_ON_RSP;
3671 }
3672 else if (strcmp(args[myidx], "match") == 0) {
3673 myidx++;
3674 flags = STK_IS_MATCH;
3675 }
3676 else if (strcmp(args[myidx], "on") == 0) {
3677 myidx++;
3678 flags = STK_IS_MATCH | STK_IS_STORE;
3679 }
3680 else {
3681 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3682 err_code |= ERR_ALERT | ERR_FATAL;
3683 goto out;
3684 }
3685
3686 if (*(args[myidx]) == 0) {
3687 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3688 err_code |= ERR_ALERT | ERR_FATAL;
3689 goto out;
3690 }
3691
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003692 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003693 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003694 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003695 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003696 err_code |= ERR_ALERT | ERR_FATAL;
3697 goto out;
3698 }
3699
3700 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003701 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3702 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3703 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003704 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003705 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003706 goto out;
3707 }
3708 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003709 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3710 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3711 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003712 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003713 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003714 goto out;
3715 }
3716 }
3717
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003718 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003719 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003720
Emeric Brunb982a3d2010-01-04 15:45:53 +01003721 if (strcmp(args[myidx], "table") == 0) {
3722 myidx++;
3723 name = args[myidx++];
3724 }
3725
Willy Tarreauef6494c2010-01-28 17:12:36 +01003726 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003727 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3728 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3729 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003730 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003731 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003732 goto out;
3733 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003734 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003735 else if (*(args[myidx])) {
3736 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3737 file, linenum, args[0], args[myidx]);
3738 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003739 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003740 goto out;
3741 }
Emeric Brun97679e72010-09-23 17:56:44 +02003742 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003743 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003744 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003745 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003746
Emeric Brunb982a3d2010-01-04 15:45:53 +01003747 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3748 rule->cond = cond;
3749 rule->expr = expr;
3750 rule->flags = flags;
3751 rule->table.name = name ? strdup(name) : NULL;
3752 LIST_INIT(&rule->list);
3753 if (flags & STK_ON_RSP)
3754 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3755 else
3756 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3757 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003758 else if (!strcmp(args[0], "stats")) {
3759 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3760 curproxy->uri_auth = NULL; /* we must detach from the default config */
3761
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003762 if (!*args[1]) {
3763 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003764 } else if (!strcmp(args[1], "admin")) {
3765 struct stats_admin_rule *rule;
3766
3767 if (curproxy == &defproxy) {
3768 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3769 err_code |= ERR_ALERT | ERR_FATAL;
3770 goto out;
3771 }
3772
3773 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3774 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3775 err_code |= ERR_ALERT | ERR_ABORT;
3776 goto out;
3777 }
3778
3779 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3780 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3781 file, linenum, args[0], args[1]);
3782 err_code |= ERR_ALERT | ERR_FATAL;
3783 goto out;
3784 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003785 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3786 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3787 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003788 err_code |= ERR_ALERT | ERR_FATAL;
3789 goto out;
3790 }
3791
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003792 err_code |= warnif_cond_conflicts(cond,
3793 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3794 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003795
3796 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3797 rule->cond = cond;
3798 LIST_INIT(&rule->list);
3799 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003800 } else if (!strcmp(args[1], "uri")) {
3801 if (*(args[2]) == 0) {
3802 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3806 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_ALERT | ERR_ABORT;
3808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809 }
3810 } else if (!strcmp(args[1], "realm")) {
3811 if (*(args[2]) == 0) {
3812 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003813 err_code |= ERR_ALERT | ERR_FATAL;
3814 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003815 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3816 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003817 err_code |= ERR_ALERT | ERR_ABORT;
3818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003819 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003820 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003821 unsigned interval;
3822
3823 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3824 if (err) {
3825 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3826 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003829 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3830 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003831 err_code |= ERR_ALERT | ERR_ABORT;
3832 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003833 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003834 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003835 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003836
3837 if (curproxy == &defproxy) {
3838 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
3841 }
3842
3843 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3844 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3845 err_code |= ERR_ALERT | ERR_ABORT;
3846 goto out;
3847 }
3848
Willy Tarreauff011f22011-01-06 17:51:27 +01003849 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3850 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003851 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3852 file, linenum, args[0]);
3853 err_code |= ERR_WARN;
3854 }
3855
Willy Tarreauff011f22011-01-06 17:51:27 +01003856 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003857
Willy Tarreauff011f22011-01-06 17:51:27 +01003858 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003859 err_code |= ERR_ALERT | ERR_ABORT;
3860 goto out;
3861 }
3862
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003863 err_code |= warnif_cond_conflicts(rule->cond,
3864 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3865 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003866 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003867
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 } else if (!strcmp(args[1], "auth")) {
3869 if (*(args[2]) == 0) {
3870 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_ALERT | ERR_FATAL;
3872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3874 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003875 err_code |= ERR_ALERT | ERR_ABORT;
3876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003877 }
3878 } else if (!strcmp(args[1], "scope")) {
3879 if (*(args[2]) == 0) {
3880 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003881 err_code |= ERR_ALERT | ERR_FATAL;
3882 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003883 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3884 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003885 err_code |= ERR_ALERT | ERR_ABORT;
3886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003887 }
3888 } else if (!strcmp(args[1], "enable")) {
3889 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3890 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003891 err_code |= ERR_ALERT | ERR_ABORT;
3892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003893 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003894 } else if (!strcmp(args[1], "hide-version")) {
3895 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3896 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003897 err_code |= ERR_ALERT | ERR_ABORT;
3898 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003899 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003900 } else if (!strcmp(args[1], "show-legends")) {
3901 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3902 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3903 err_code |= ERR_ALERT | ERR_ABORT;
3904 goto out;
3905 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003906 } else if (!strcmp(args[1], "show-node")) {
3907
3908 if (*args[2]) {
3909 int i;
3910 char c;
3911
3912 for (i=0; args[2][i]; i++) {
3913 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003914 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3915 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003916 break;
3917 }
3918
3919 if (!i || args[2][i]) {
3920 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3921 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3922 file, linenum, args[0], args[1]);
3923 err_code |= ERR_ALERT | ERR_FATAL;
3924 goto out;
3925 }
3926 }
3927
3928 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3929 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3930 err_code |= ERR_ALERT | ERR_ABORT;
3931 goto out;
3932 }
3933 } else if (!strcmp(args[1], "show-desc")) {
3934 char *desc = NULL;
3935
3936 if (*args[2]) {
3937 int i, len=0;
3938 char *d;
3939
Willy Tarreau348acfe2014-04-14 15:00:39 +02003940 for (i = 2; *args[i]; i++)
3941 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003942
3943 desc = d = (char *)calloc(1, len);
3944
Willy Tarreau348acfe2014-04-14 15:00:39 +02003945 d += snprintf(d, desc + len - d, "%s", args[2]);
3946 for (i = 3; *args[i]; i++)
3947 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003948 }
3949
3950 if (!*args[2] && !global.desc)
3951 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3952 file, linenum, args[1]);
3953 else {
3954 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3955 free(desc);
3956 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3957 err_code |= ERR_ALERT | ERR_ABORT;
3958 goto out;
3959 }
3960 free(desc);
3961 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003962 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003963stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003964 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 +01003965 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003968 }
3969 }
3970 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003971 int optnum;
3972
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003973 if (*(args[1]) == '\0') {
3974 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3975 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003976 err_code |= ERR_ALERT | ERR_FATAL;
3977 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003978 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003979
3980 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3981 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003982 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3983 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3984 file, linenum, cfg_opts[optnum].name);
3985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
3987 }
Willy Tarreau93893792009-07-23 13:19:11 +02003988 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3989 err_code |= ERR_WARN;
3990 goto out;
3991 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003992
Willy Tarreau3842f002009-06-14 11:39:52 +02003993 curproxy->no_options &= ~cfg_opts[optnum].val;
3994 curproxy->options &= ~cfg_opts[optnum].val;
3995
3996 switch (kwm) {
3997 case KWM_STD:
3998 curproxy->options |= cfg_opts[optnum].val;
3999 break;
4000 case KWM_NO:
4001 curproxy->no_options |= cfg_opts[optnum].val;
4002 break;
4003 case KWM_DEF: /* already cleared */
4004 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004005 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004006
Willy Tarreau93893792009-07-23 13:19:11 +02004007 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004008 }
4009 }
4010
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004011 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4012 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004013 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4014 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4015 file, linenum, cfg_opts2[optnum].name);
4016 err_code |= ERR_ALERT | ERR_FATAL;
4017 goto out;
4018 }
Willy Tarreau93893792009-07-23 13:19:11 +02004019 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4020 err_code |= ERR_WARN;
4021 goto out;
4022 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004023
Willy Tarreau3842f002009-06-14 11:39:52 +02004024 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4025 curproxy->options2 &= ~cfg_opts2[optnum].val;
4026
4027 switch (kwm) {
4028 case KWM_STD:
4029 curproxy->options2 |= cfg_opts2[optnum].val;
4030 break;
4031 case KWM_NO:
4032 curproxy->no_options2 |= cfg_opts2[optnum].val;
4033 break;
4034 case KWM_DEF: /* already cleared */
4035 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004036 }
Willy Tarreau93893792009-07-23 13:19:11 +02004037 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004038 }
4039 }
4040
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004041 /* HTTP options override each other. They can be cancelled using
4042 * "no option xxx" which only switches to default mode if the mode
4043 * was this one (useful for cancelling options set in defaults
4044 * sections).
4045 */
4046 if (strcmp(args[1], "httpclose") == 0) {
4047 if (kwm == KWM_STD) {
4048 curproxy->options &= ~PR_O_HTTP_MODE;
4049 curproxy->options |= PR_O_HTTP_PCL;
4050 goto out;
4051 }
4052 else if (kwm == KWM_NO) {
4053 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4054 curproxy->options &= ~PR_O_HTTP_MODE;
4055 goto out;
4056 }
4057 }
4058 else if (strcmp(args[1], "forceclose") == 0) {
4059 if (kwm == KWM_STD) {
4060 curproxy->options &= ~PR_O_HTTP_MODE;
4061 curproxy->options |= PR_O_HTTP_FCL;
4062 goto out;
4063 }
4064 else if (kwm == KWM_NO) {
4065 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4066 curproxy->options &= ~PR_O_HTTP_MODE;
4067 goto out;
4068 }
4069 }
4070 else if (strcmp(args[1], "http-server-close") == 0) {
4071 if (kwm == KWM_STD) {
4072 curproxy->options &= ~PR_O_HTTP_MODE;
4073 curproxy->options |= PR_O_HTTP_SCL;
4074 goto out;
4075 }
4076 else if (kwm == KWM_NO) {
4077 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4078 curproxy->options &= ~PR_O_HTTP_MODE;
4079 goto out;
4080 }
4081 }
4082 else if (strcmp(args[1], "http-keep-alive") == 0) {
4083 if (kwm == KWM_STD) {
4084 curproxy->options &= ~PR_O_HTTP_MODE;
4085 curproxy->options |= PR_O_HTTP_KAL;
4086 goto out;
4087 }
4088 else if (kwm == KWM_NO) {
4089 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4090 curproxy->options &= ~PR_O_HTTP_MODE;
4091 goto out;
4092 }
4093 }
4094 else if (strcmp(args[1], "http-tunnel") == 0) {
4095 if (kwm == KWM_STD) {
4096 curproxy->options &= ~PR_O_HTTP_MODE;
4097 curproxy->options |= PR_O_HTTP_TUN;
4098 goto out;
4099 }
4100 else if (kwm == KWM_NO) {
4101 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4102 curproxy->options &= ~PR_O_HTTP_MODE;
4103 goto out;
4104 }
4105 }
4106
Joseph Lynch726ab712015-05-11 23:25:34 -07004107 /* Redispatch can take an integer argument that control when the
4108 * resispatch occurs. All values are relative to the retries option.
4109 * This can be cancelled using "no option xxx".
4110 */
4111 if (strcmp(args[1], "redispatch") == 0) {
4112 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4113 err_code |= ERR_WARN;
4114 goto out;
4115 }
4116
4117 curproxy->no_options &= ~PR_O_REDISP;
4118 curproxy->options &= ~PR_O_REDISP;
4119
4120 switch (kwm) {
4121 case KWM_STD:
4122 curproxy->options |= PR_O_REDISP;
4123 curproxy->redispatch_after = -1;
4124 if(*args[2]) {
4125 curproxy->redispatch_after = atol(args[2]);
4126 }
4127 break;
4128 case KWM_NO:
4129 curproxy->no_options |= PR_O_REDISP;
4130 curproxy->redispatch_after = 0;
4131 break;
4132 case KWM_DEF: /* already cleared */
4133 break;
4134 }
4135 goto out;
4136 }
4137
Willy Tarreau3842f002009-06-14 11:39:52 +02004138 if (kwm != KWM_STD) {
4139 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004140 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004141 err_code |= ERR_ALERT | ERR_FATAL;
4142 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004143 }
4144
Emeric Brun3a058f32009-06-30 18:26:00 +02004145 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004146 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004147 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004148 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004149 if (*(args[2]) != '\0') {
4150 if (!strcmp(args[2], "clf")) {
4151 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004152 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004153 } else {
4154 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02004155 err_code |= ERR_ALERT | ERR_FATAL;
4156 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004157 }
4158 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004159 if (curproxy->conf.logformat_string != default_http_log_format &&
4160 curproxy->conf.logformat_string != default_tcp_log_format &&
4161 curproxy->conf.logformat_string != clf_http_log_format)
4162 free(curproxy->conf.logformat_string);
4163 curproxy->conf.logformat_string = logformat;
4164
4165 free(curproxy->conf.lfs_file);
4166 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4167 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004168 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004169 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004170 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004171 if (curproxy->conf.logformat_string != default_http_log_format &&
4172 curproxy->conf.logformat_string != default_tcp_log_format &&
4173 curproxy->conf.logformat_string != clf_http_log_format)
4174 free(curproxy->conf.logformat_string);
4175 curproxy->conf.logformat_string = default_tcp_log_format;
4176
4177 free(curproxy->conf.lfs_file);
4178 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4179 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004180 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004181 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004182 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004183 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004184 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004185
4186 if (curproxy->cap & PR_CAP_FE)
4187 curproxy->options |= PR_O_TCP_CLI_KA;
4188 if (curproxy->cap & PR_CAP_BE)
4189 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004190 }
4191 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004192 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004193 err_code |= ERR_WARN;
4194
Willy Tarreaubaaee002006-06-26 02:48:02 +02004195 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004196 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004197 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004198 curproxy->options2 &= ~PR_O2_CHK_ANY;
4199 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004200 if (!*args[2]) { /* no argument */
4201 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4202 curproxy->check_len = strlen(DEF_CHECK_REQ);
4203 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004204 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004205 curproxy->check_req = (char *)malloc(reqlen);
4206 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004207 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004208 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004209 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004210 if (*args[4])
4211 reqlen += strlen(args[4]);
4212 else
4213 reqlen += strlen("HTTP/1.0");
4214
4215 curproxy->check_req = (char *)malloc(reqlen);
4216 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004217 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004218 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004219 }
4220 else if (!strcmp(args[1], "ssl-hello-chk")) {
4221 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004222 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004223 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004224
Willy Tarreaua534fea2008-08-03 12:19:50 +02004225 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004226 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004227 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004228 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004229 }
Willy Tarreau23677902007-05-08 23:50:35 +02004230 else if (!strcmp(args[1], "smtpchk")) {
4231 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004232 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004233 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004234 curproxy->options2 &= ~PR_O2_CHK_ANY;
4235 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004236
4237 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4238 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4239 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4240 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4241 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4242 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4243 curproxy->check_req = (char *)malloc(reqlen);
4244 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4245 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4246 } else {
4247 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4248 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4249 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4250 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4251 }
4252 }
4253 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004254 else if (!strcmp(args[1], "pgsql-check")) {
4255 /* use PostgreSQL request to check servers' health */
4256 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4257 err_code |= ERR_WARN;
4258
4259 free(curproxy->check_req);
4260 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004261 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004262 curproxy->options2 |= PR_O2_PGSQL_CHK;
4263
4264 if (*(args[2])) {
4265 int cur_arg = 2;
4266
4267 while (*(args[cur_arg])) {
4268 if (strcmp(args[cur_arg], "user") == 0) {
4269 char * packet;
4270 uint32_t packet_len;
4271 uint32_t pv;
4272
4273 /* suboption header - needs additional argument for it */
4274 if (*(args[cur_arg+1]) == 0) {
4275 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4276 file, linenum, args[0], args[1], args[cur_arg]);
4277 err_code |= ERR_ALERT | ERR_FATAL;
4278 goto out;
4279 }
4280
4281 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4282 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4283 pv = htonl(0x30000); /* protocol version 3.0 */
4284
4285 packet = (char*) calloc(1, packet_len);
4286
4287 memcpy(packet + 4, &pv, 4);
4288
4289 /* copy "user" */
4290 memcpy(packet + 8, "user", 4);
4291
4292 /* copy username */
4293 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4294
4295 free(curproxy->check_req);
4296 curproxy->check_req = packet;
4297 curproxy->check_len = packet_len;
4298
4299 packet_len = htonl(packet_len);
4300 memcpy(packet, &packet_len, 4);
4301 cur_arg += 2;
4302 } else {
4303 /* unknown suboption - catchall */
4304 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4305 file, linenum, args[0], args[1]);
4306 err_code |= ERR_ALERT | ERR_FATAL;
4307 goto out;
4308 }
4309 } /* end while loop */
4310 }
4311 }
4312
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004313 else if (!strcmp(args[1], "redis-check")) {
4314 /* use REDIS PING request to check servers' health */
4315 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4316 err_code |= ERR_WARN;
4317
4318 free(curproxy->check_req);
4319 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004320 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004321 curproxy->options2 |= PR_O2_REDIS_CHK;
4322
4323 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4324 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4325 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4326 }
4327
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004328 else if (!strcmp(args[1], "mysql-check")) {
4329 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004330 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4331 err_code |= ERR_WARN;
4332
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004333 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004334 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004335 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004336 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004337
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004338 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004339 * const char mysql40_client_auth_pkt[] = {
4340 * "\x0e\x00\x00" // packet length
4341 * "\x01" // packet number
4342 * "\x00\x00" // client capabilities
4343 * "\x00\x00\x01" // max packet
4344 * "haproxy\x00" // username (null terminated string)
4345 * "\x00" // filler (always 0x00)
4346 * "\x01\x00\x00" // packet length
4347 * "\x00" // packet number
4348 * "\x01" // COM_QUIT command
4349 * };
4350 */
4351
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004352 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4353 * const char mysql41_client_auth_pkt[] = {
4354 * "\x0e\x00\x00\" // packet length
4355 * "\x01" // packet number
4356 * "\x00\x00\x00\x00" // client capabilities
4357 * "\x00\x00\x00\x01" // max packet
4358 * "\x21" // character set (UTF-8)
4359 * char[23] // All zeroes
4360 * "haproxy\x00" // username (null terminated string)
4361 * "\x00" // filler (always 0x00)
4362 * "\x01\x00\x00" // packet length
4363 * "\x00" // packet number
4364 * "\x01" // COM_QUIT command
4365 * };
4366 */
4367
4368
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004369 if (*(args[2])) {
4370 int cur_arg = 2;
4371
4372 while (*(args[cur_arg])) {
4373 if (strcmp(args[cur_arg], "user") == 0) {
4374 char *mysqluser;
4375 int packetlen, reqlen, userlen;
4376
4377 /* suboption header - needs additional argument for it */
4378 if (*(args[cur_arg+1]) == 0) {
4379 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4380 file, linenum, args[0], args[1], args[cur_arg]);
4381 err_code |= ERR_ALERT | ERR_FATAL;
4382 goto out;
4383 }
4384 mysqluser = args[cur_arg + 1];
4385 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004386
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004387 if (*(args[cur_arg+2])) {
4388 if (!strcmp(args[cur_arg+2], "post-41")) {
4389 packetlen = userlen + 7 + 27;
4390 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004391
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004392 free(curproxy->check_req);
4393 curproxy->check_req = (char *)calloc(1, reqlen);
4394 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004395
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004396 snprintf(curproxy->check_req, 4, "%c%c%c",
4397 ((unsigned char) packetlen & 0xff),
4398 ((unsigned char) (packetlen >> 8) & 0xff),
4399 ((unsigned char) (packetlen >> 16) & 0xff));
4400
4401 curproxy->check_req[3] = 1;
4402 curproxy->check_req[5] = 130;
4403 curproxy->check_req[11] = 1;
4404 curproxy->check_req[12] = 33;
4405 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4406 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4407 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4408 cur_arg += 3;
4409 } else {
4410 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4411 err_code |= ERR_ALERT | ERR_FATAL;
4412 goto out;
4413 }
4414 } else {
4415 packetlen = userlen + 7;
4416 reqlen = packetlen + 9;
4417
4418 free(curproxy->check_req);
4419 curproxy->check_req = (char *)calloc(1, reqlen);
4420 curproxy->check_len = reqlen;
4421
4422 snprintf(curproxy->check_req, 4, "%c%c%c",
4423 ((unsigned char) packetlen & 0xff),
4424 ((unsigned char) (packetlen >> 8) & 0xff),
4425 ((unsigned char) (packetlen >> 16) & 0xff));
4426
4427 curproxy->check_req[3] = 1;
4428 curproxy->check_req[5] = 128;
4429 curproxy->check_req[8] = 1;
4430 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4431 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4432 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4433 cur_arg += 2;
4434 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004435 } else {
4436 /* unknown suboption - catchall */
4437 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4438 file, linenum, args[0], args[1]);
4439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
4441 }
4442 } /* end while loop */
4443 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004444 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004445 else if (!strcmp(args[1], "ldap-check")) {
4446 /* use LDAP request to check servers' health */
4447 free(curproxy->check_req);
4448 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004449 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004450 curproxy->options2 |= PR_O2_LDAP_CHK;
4451
4452 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4453 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4454 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4455 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004456 else if (!strcmp(args[1], "tcp-check")) {
4457 /* use raw TCPCHK send/expect to check servers' health */
4458 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4459 err_code |= ERR_WARN;
4460
4461 free(curproxy->check_req);
4462 curproxy->check_req = NULL;
4463 curproxy->options2 &= ~PR_O2_CHK_ANY;
4464 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4465 }
Simon Horman98637e52014-06-20 12:30:16 +09004466 else if (!strcmp(args[1], "external-check")) {
4467 /* excute an external command to check servers' health */
4468 free(curproxy->check_req);
4469 curproxy->check_req = NULL;
4470 curproxy->options2 &= ~PR_O2_CHK_ANY;
4471 curproxy->options2 |= PR_O2_EXT_CHK;
4472 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004473 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004474 int cur_arg;
4475
4476 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4477 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004478 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004479
Willy Tarreau87cf5142011-08-19 22:57:24 +02004480 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004481
4482 free(curproxy->fwdfor_hdr_name);
4483 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4484 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4485
4486 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4487 cur_arg = 2;
4488 while (*(args[cur_arg])) {
4489 if (!strcmp(args[cur_arg], "except")) {
4490 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004491 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004492 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4493 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004494 err_code |= ERR_ALERT | ERR_FATAL;
4495 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004496 }
4497 /* flush useless bits */
4498 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004499 cur_arg += 2;
4500 } else if (!strcmp(args[cur_arg], "header")) {
4501 /* suboption header - needs additional argument for it */
4502 if (*(args[cur_arg+1]) == 0) {
4503 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4504 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004505 err_code |= ERR_ALERT | ERR_FATAL;
4506 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004507 }
4508 free(curproxy->fwdfor_hdr_name);
4509 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4510 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4511 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004512 } else if (!strcmp(args[cur_arg], "if-none")) {
4513 curproxy->options &= ~PR_O_FF_ALWAYS;
4514 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004515 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004516 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004517 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004518 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004519 err_code |= ERR_ALERT | ERR_FATAL;
4520 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004521 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004522 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004523 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004524 else if (!strcmp(args[1], "originalto")) {
4525 int cur_arg;
4526
4527 /* insert x-original-to field, but not for the IP address listed as an except.
4528 * set default options (ie: bitfield, header name, etc)
4529 */
4530
4531 curproxy->options |= PR_O_ORGTO;
4532
4533 free(curproxy->orgto_hdr_name);
4534 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4535 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4536
Willy Tarreau87cf5142011-08-19 22:57:24 +02004537 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004538 cur_arg = 2;
4539 while (*(args[cur_arg])) {
4540 if (!strcmp(args[cur_arg], "except")) {
4541 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004542 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 +02004543 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4544 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004545 err_code |= ERR_ALERT | ERR_FATAL;
4546 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004547 }
4548 /* flush useless bits */
4549 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4550 cur_arg += 2;
4551 } else if (!strcmp(args[cur_arg], "header")) {
4552 /* suboption header - needs additional argument for it */
4553 if (*(args[cur_arg+1]) == 0) {
4554 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4555 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004556 err_code |= ERR_ALERT | ERR_FATAL;
4557 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004558 }
4559 free(curproxy->orgto_hdr_name);
4560 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4561 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4562 cur_arg += 2;
4563 } else {
4564 /* unknown suboption - catchall */
4565 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4566 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004567 err_code |= ERR_ALERT | ERR_FATAL;
4568 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004569 }
4570 } /* end while loop */
4571 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004572 else {
4573 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004574 err_code |= ERR_ALERT | ERR_FATAL;
4575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004576 }
Willy Tarreau93893792009-07-23 13:19:11 +02004577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004578 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004579 else if (!strcmp(args[0], "default_backend")) {
4580 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004581 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004582
4583 if (*(args[1]) == 0) {
4584 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004585 err_code |= ERR_ALERT | ERR_FATAL;
4586 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004587 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004588 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004589 curproxy->defbe.name = strdup(args[1]);
4590 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004591 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004592 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004593 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004594
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004595 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4596 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 +01004597 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004598 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004599 /* enable reconnections to dispatch */
4600 curproxy->options |= PR_O_REDISP;
4601 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004602 else if (!strcmp(args[0], "http-check")) {
4603 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004604 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004605
4606 if (strcmp(args[1], "disable-on-404") == 0) {
4607 /* enable a graceful server shutdown on an HTTP 404 response */
4608 curproxy->options |= PR_O_DISABLE404;
4609 }
Willy Tarreauef781042010-01-27 11:53:01 +01004610 else if (strcmp(args[1], "send-state") == 0) {
4611 /* enable emission of the apparent state of a server in HTTP checks */
4612 curproxy->options2 |= PR_O2_CHK_SNDST;
4613 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004614 else if (strcmp(args[1], "expect") == 0) {
4615 const char *ptr_arg;
4616 int cur_arg;
4617
4618 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4619 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4620 err_code |= ERR_ALERT | ERR_FATAL;
4621 goto out;
4622 }
4623
4624 cur_arg = 2;
4625 /* consider exclamation marks, sole or at the beginning of a word */
4626 while (*(ptr_arg = args[cur_arg])) {
4627 while (*ptr_arg == '!') {
4628 curproxy->options2 ^= PR_O2_EXP_INV;
4629 ptr_arg++;
4630 }
4631 if (*ptr_arg)
4632 break;
4633 cur_arg++;
4634 }
4635 /* now ptr_arg points to the beginning of a word past any possible
4636 * exclamation mark, and cur_arg is the argument which holds this word.
4637 */
4638 if (strcmp(ptr_arg, "status") == 0) {
4639 if (!*(args[cur_arg + 1])) {
4640 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4641 file, linenum, args[0], args[1], ptr_arg);
4642 err_code |= ERR_ALERT | ERR_FATAL;
4643 goto out;
4644 }
4645 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004646 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004647 curproxy->expect_str = strdup(args[cur_arg + 1]);
4648 }
4649 else if (strcmp(ptr_arg, "string") == 0) {
4650 if (!*(args[cur_arg + 1])) {
4651 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4652 file, linenum, args[0], args[1], ptr_arg);
4653 err_code |= ERR_ALERT | ERR_FATAL;
4654 goto out;
4655 }
4656 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004657 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004658 curproxy->expect_str = strdup(args[cur_arg + 1]);
4659 }
4660 else if (strcmp(ptr_arg, "rstatus") == 0) {
4661 if (!*(args[cur_arg + 1])) {
4662 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4663 file, linenum, args[0], args[1], ptr_arg);
4664 err_code |= ERR_ALERT | ERR_FATAL;
4665 goto out;
4666 }
4667 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004668 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004669 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004670 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004671 free(curproxy->expect_regex);
4672 curproxy->expect_regex = NULL;
4673 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004674 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004675 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4676 error = NULL;
4677 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4678 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4679 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4680 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004681 err_code |= ERR_ALERT | ERR_FATAL;
4682 goto out;
4683 }
4684 }
4685 else if (strcmp(ptr_arg, "rstring") == 0) {
4686 if (!*(args[cur_arg + 1])) {
4687 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4688 file, linenum, args[0], args[1], ptr_arg);
4689 err_code |= ERR_ALERT | ERR_FATAL;
4690 goto out;
4691 }
4692 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004693 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004694 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004695 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004696 free(curproxy->expect_regex);
4697 curproxy->expect_regex = NULL;
4698 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004699 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004700 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4701 error = NULL;
4702 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4703 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4704 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4705 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004706 err_code |= ERR_ALERT | ERR_FATAL;
4707 goto out;
4708 }
4709 }
4710 else {
4711 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4712 file, linenum, args[0], args[1], ptr_arg);
4713 err_code |= ERR_ALERT | ERR_FATAL;
4714 goto out;
4715 }
4716 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004717 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004718 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 +02004719 err_code |= ERR_ALERT | ERR_FATAL;
4720 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004721 }
4722 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004723 else if (!strcmp(args[0], "tcp-check")) {
4724 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4725 err_code |= ERR_WARN;
4726
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004727 if (strcmp(args[1], "comment") == 0) {
4728 int cur_arg;
4729 struct tcpcheck_rule *tcpcheck;
4730
4731 cur_arg = 1;
4732 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4733 tcpcheck->action = TCPCHK_ACT_COMMENT;
4734
4735 if (!*args[cur_arg + 1]) {
4736 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4737 file, linenum, args[cur_arg]);
4738 err_code |= ERR_ALERT | ERR_FATAL;
4739 goto out;
4740 }
4741
4742 tcpcheck->comment = strdup(args[cur_arg + 1]);
4743
4744 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4745 }
4746 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004747 const char *ptr_arg;
4748 int cur_arg;
4749 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004750
4751 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02004752 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
4753 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
4754 tcpcheck->action == TCPCHK_ACT_COMMENT) {
4755 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
4756 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004757
Willy Tarreau5581c272015-05-13 12:24:53 +02004758 if (&tcpcheck->list != &curproxy->tcpcheck_rules
4759 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4760 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4761 file, linenum);
4762 err_code |= ERR_ALERT | ERR_FATAL;
4763 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004764 }
4765
4766 cur_arg = 2;
4767 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4768 tcpcheck->action = TCPCHK_ACT_CONNECT;
4769
4770 /* parsing each parameters to fill up the rule */
4771 while (*(ptr_arg = args[cur_arg])) {
4772 /* tcp port */
4773 if (strcmp(args[cur_arg], "port") == 0) {
4774 if ( (atol(args[cur_arg + 1]) > 65535) ||
4775 (atol(args[cur_arg + 1]) < 1) ){
4776 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4777 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4778 err_code |= ERR_ALERT | ERR_FATAL;
4779 goto out;
4780 }
4781 tcpcheck->port = atol(args[cur_arg + 1]);
4782 cur_arg += 2;
4783 }
4784 /* send proxy protocol */
4785 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4786 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4787 cur_arg++;
4788 }
4789#ifdef USE_OPENSSL
4790 else if (strcmp(args[cur_arg], "ssl") == 0) {
4791 curproxy->options |= PR_O_TCPCHK_SSL;
4792 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4793 cur_arg++;
4794 }
4795#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004796 /* comment for this tcpcheck line */
4797 else if (strcmp(args[cur_arg], "comment") == 0) {
4798 if (!*args[cur_arg + 1]) {
4799 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4800 file, linenum, args[cur_arg]);
4801 err_code |= ERR_ALERT | ERR_FATAL;
4802 goto out;
4803 }
4804 tcpcheck->comment = strdup(args[cur_arg + 1]);
4805 cur_arg += 2;
4806 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004807 else {
4808#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004809 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 +01004810#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004811 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 +01004812#endif /* USE_OPENSSL */
4813 file, linenum, args[0], args[1], args[cur_arg]);
4814 err_code |= ERR_ALERT | ERR_FATAL;
4815 goto out;
4816 }
4817
4818 }
4819
4820 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4821 }
4822 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004823 if (! *(args[2]) ) {
4824 /* SEND string expected */
4825 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4826 file, linenum, args[0], args[1], args[2]);
4827 err_code |= ERR_ALERT | ERR_FATAL;
4828 goto out;
4829 } else {
4830 struct tcpcheck_rule *tcpcheck;
4831
4832 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4833
4834 tcpcheck->action = TCPCHK_ACT_SEND;
4835 tcpcheck->string_len = strlen(args[2]);
4836 tcpcheck->string = strdup(args[2]);
4837 tcpcheck->expect_regex = NULL;
4838
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004839 /* comment for this tcpcheck line */
4840 if (strcmp(args[3], "comment") == 0) {
4841 if (!*args[4]) {
4842 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4843 file, linenum, args[3]);
4844 err_code |= ERR_ALERT | ERR_FATAL;
4845 goto out;
4846 }
4847 tcpcheck->comment = strdup(args[4]);
4848 }
4849
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004850 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4851 }
4852 }
4853 else if (strcmp(args[1], "send-binary") == 0) {
4854 if (! *(args[2]) ) {
4855 /* SEND binary string expected */
4856 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4857 file, linenum, args[0], args[1], args[2]);
4858 err_code |= ERR_ALERT | ERR_FATAL;
4859 goto out;
4860 } else {
4861 struct tcpcheck_rule *tcpcheck;
4862 char *err = NULL;
4863
4864 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4865
4866 tcpcheck->action = TCPCHK_ACT_SEND;
4867 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4868 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4869 file, linenum, args[0], args[1], args[2], err);
4870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
4872 }
4873 tcpcheck->expect_regex = NULL;
4874
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004875 /* comment for this tcpcheck line */
4876 if (strcmp(args[3], "comment") == 0) {
4877 if (!*args[4]) {
4878 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4879 file, linenum, args[3]);
4880 err_code |= ERR_ALERT | ERR_FATAL;
4881 goto out;
4882 }
4883 tcpcheck->comment = strdup(args[4]);
4884 }
4885
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004886 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4887 }
4888 }
4889 else if (strcmp(args[1], "expect") == 0) {
4890 const char *ptr_arg;
4891 int cur_arg;
4892 int inverse = 0;
4893
4894 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4895 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4896 err_code |= ERR_ALERT | ERR_FATAL;
4897 goto out;
4898 }
4899
4900 cur_arg = 2;
4901 /* consider exclamation marks, sole or at the beginning of a word */
4902 while (*(ptr_arg = args[cur_arg])) {
4903 while (*ptr_arg == '!') {
4904 inverse = !inverse;
4905 ptr_arg++;
4906 }
4907 if (*ptr_arg)
4908 break;
4909 cur_arg++;
4910 }
4911 /* now ptr_arg points to the beginning of a word past any possible
4912 * exclamation mark, and cur_arg is the argument which holds this word.
4913 */
4914 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004915 struct tcpcheck_rule *tcpcheck;
4916 char *err = NULL;
4917
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004918 if (!*(args[cur_arg + 1])) {
4919 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4920 file, linenum, args[0], args[1], ptr_arg);
4921 err_code |= ERR_ALERT | ERR_FATAL;
4922 goto out;
4923 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004924
4925 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4926
4927 tcpcheck->action = TCPCHK_ACT_EXPECT;
4928 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4929 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4930 file, linenum, args[0], args[1], args[2], err);
4931 err_code |= ERR_ALERT | ERR_FATAL;
4932 goto out;
4933 }
4934 tcpcheck->expect_regex = NULL;
4935 tcpcheck->inverse = inverse;
4936
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004937 /* tcpcheck comment */
4938 cur_arg += 2;
4939 if (strcmp(args[cur_arg], "comment") == 0) {
4940 if (!*args[cur_arg + 1]) {
4941 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4942 file, linenum, args[cur_arg + 1]);
4943 err_code |= ERR_ALERT | ERR_FATAL;
4944 goto out;
4945 }
4946 tcpcheck->comment = strdup(args[cur_arg + 1]);
4947 }
4948
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004949 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4950 }
4951 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004952 struct tcpcheck_rule *tcpcheck;
4953
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004954 if (!*(args[cur_arg + 1])) {
4955 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4956 file, linenum, args[0], args[1], ptr_arg);
4957 err_code |= ERR_ALERT | ERR_FATAL;
4958 goto out;
4959 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004960
4961 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4962
4963 tcpcheck->action = TCPCHK_ACT_EXPECT;
4964 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4965 tcpcheck->string = strdup(args[cur_arg + 1]);
4966 tcpcheck->expect_regex = NULL;
4967 tcpcheck->inverse = inverse;
4968
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004969 /* tcpcheck comment */
4970 cur_arg += 2;
4971 if (strcmp(args[cur_arg], "comment") == 0) {
4972 if (!*args[cur_arg + 1]) {
4973 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4974 file, linenum, args[cur_arg + 1]);
4975 err_code |= ERR_ALERT | ERR_FATAL;
4976 goto out;
4977 }
4978 tcpcheck->comment = strdup(args[cur_arg + 1]);
4979 }
4980
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004981 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4982 }
4983 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004984 struct tcpcheck_rule *tcpcheck;
4985
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004986 if (!*(args[cur_arg + 1])) {
4987 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4988 file, linenum, args[0], args[1], ptr_arg);
4989 err_code |= ERR_ALERT | ERR_FATAL;
4990 goto out;
4991 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004992
4993 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4994
4995 tcpcheck->action = TCPCHK_ACT_EXPECT;
4996 tcpcheck->string_len = 0;
4997 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004998 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4999 error = NULL;
5000 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5001 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5002 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5003 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005004 err_code |= ERR_ALERT | ERR_FATAL;
5005 goto out;
5006 }
5007 tcpcheck->inverse = inverse;
5008
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005009 /* tcpcheck comment */
5010 cur_arg += 2;
5011 if (strcmp(args[cur_arg], "comment") == 0) {
5012 if (!*args[cur_arg + 1]) {
5013 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5014 file, linenum, args[cur_arg + 1]);
5015 err_code |= ERR_ALERT | ERR_FATAL;
5016 goto out;
5017 }
5018 tcpcheck->comment = strdup(args[cur_arg + 1]);
5019 }
5020
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005021 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5022 }
5023 else {
5024 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5025 file, linenum, args[0], args[1], ptr_arg);
5026 err_code |= ERR_ALERT | ERR_FATAL;
5027 goto out;
5028 }
5029 }
5030 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005031 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005032 err_code |= ERR_ALERT | ERR_FATAL;
5033 goto out;
5034 }
5035 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005036 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005037 if (curproxy == &defproxy) {
5038 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005039 err_code |= ERR_ALERT | ERR_FATAL;
5040 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005041 }
5042
Willy Tarreaub80c2302007-11-30 20:51:32 +01005043 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005044 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005045
5046 if (strcmp(args[1], "fail") == 0) {
5047 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005048 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005049 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5050 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005051 err_code |= ERR_ALERT | ERR_FATAL;
5052 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005053 }
5054
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005055 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5056 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5057 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005058 err_code |= ERR_ALERT | ERR_FATAL;
5059 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005060 }
5061 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5062 }
5063 else {
5064 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005065 err_code |= ERR_ALERT | ERR_FATAL;
5066 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005067 }
5068 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005069#ifdef TPROXY
5070 else if (!strcmp(args[0], "transparent")) {
5071 /* enable transparent proxy connections */
5072 curproxy->options |= PR_O_TRANSP;
5073 }
5074#endif
5075 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005076 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005077 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005078
Willy Tarreaubaaee002006-06-26 02:48:02 +02005079 if (*(args[1]) == 0) {
5080 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005081 err_code |= ERR_ALERT | ERR_FATAL;
5082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005083 }
5084 curproxy->maxconn = atol(args[1]);
5085 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005086 else if (!strcmp(args[0], "backlog")) { /* backlog */
5087 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005088 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005089
5090 if (*(args[1]) == 0) {
5091 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005092 err_code |= ERR_ALERT | ERR_FATAL;
5093 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005094 }
5095 curproxy->backlog = atol(args[1]);
5096 }
Willy Tarreau86034312006-12-29 00:10:33 +01005097 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005098 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005099 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005100
Willy Tarreau86034312006-12-29 00:10:33 +01005101 if (*(args[1]) == 0) {
5102 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005103 err_code |= ERR_ALERT | ERR_FATAL;
5104 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005105 }
5106 curproxy->fullconn = atol(args[1]);
5107 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005108 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5109 if (*(args[1]) == 0) {
5110 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\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 Tarreaub3f32f52007-12-02 22:15:14 +01005114 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5115 if (err) {
5116 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5117 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005118 err_code |= ERR_ALERT | ERR_FATAL;
5119 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005120 }
5121 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005122 }
5123 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005124 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005125 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005126 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005127
Willy Tarreaubaaee002006-06-26 02:48:02 +02005128 if (curproxy == &defproxy) {
5129 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005130 err_code |= ERR_ALERT | ERR_FATAL;
5131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005132 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005133 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005134 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005135
Willy Tarreau902636f2013-03-10 19:44:48 +01005136 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005137 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005138 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005139 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005140 goto out;
5141 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005142
5143 proto = protocol_by_family(sk->ss_family);
5144 if (!proto || !proto->connect) {
5145 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5146 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005147 err_code |= ERR_ALERT | ERR_FATAL;
5148 goto out;
5149 }
5150
5151 if (port1 != port2) {
5152 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5153 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005156 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005157
5158 if (!port1) {
5159 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5160 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005161 err_code |= ERR_ALERT | ERR_FATAL;
5162 goto out;
5163 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005164
Willy Tarreaud5191e72010-02-09 20:50:45 +01005165 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005166 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005167 }
5168 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005169 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005170 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005171
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005172 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5173 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005174 err_code |= ERR_ALERT | ERR_FATAL;
5175 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005176 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005177 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005178 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005179 /**
5180 * The syntax for hash-type config element is
5181 * hash-type {map-based|consistent} [[<algo>] avalanche]
5182 *
5183 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5184 */
5185 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005186
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005187 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5188 err_code |= ERR_WARN;
5189
5190 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005191 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5192 }
5193 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005194 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5195 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005196 else if (strcmp(args[1], "avalanche") == 0) {
5197 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]);
5198 err_code |= ERR_ALERT | ERR_FATAL;
5199 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005200 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005201 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005202 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005203 err_code |= ERR_ALERT | ERR_FATAL;
5204 goto out;
5205 }
Bhaskar98634f02013-10-29 23:30:51 -04005206
5207 /* set the hash function to use */
5208 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005209 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005210 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005211
5212 /* if consistent with no argument, then avalanche modifier is also applied */
5213 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5214 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005215 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005216 /* set the hash function */
5217 if (!strcmp(args[2], "sdbm")) {
5218 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5219 }
5220 else if (!strcmp(args[2], "djb2")) {
5221 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005222 }
5223 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005224 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005225 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005226 else if (!strcmp(args[2], "crc32")) {
5227 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5228 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005229 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005230 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 -05005231 err_code |= ERR_ALERT | ERR_FATAL;
5232 goto out;
5233 }
5234
5235 /* set the hash modifier */
5236 if (!strcmp(args[3], "avalanche")) {
5237 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5238 }
5239 else if (*args[3]) {
5240 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5241 err_code |= ERR_ALERT | ERR_FATAL;
5242 goto out;
5243 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005244 }
William Lallemanda73203e2012-03-12 12:48:57 +01005245 }
William Lallemanda73203e2012-03-12 12:48:57 +01005246 else if (strcmp(args[0], "unique-id-format") == 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 }
William Lallemand3203ff42012-11-11 17:30:56 +01005252 if (*(args[2])) {
5253 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5254 err_code |= ERR_ALERT | ERR_FATAL;
5255 goto out;
5256 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005257 free(curproxy->conf.uniqueid_format_string);
5258 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005259
Willy Tarreau62a61232013-04-12 18:13:46 +02005260 free(curproxy->conf.uif_file);
5261 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5262 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005263 }
William Lallemanda73203e2012-03-12 12:48:57 +01005264
5265 else if (strcmp(args[0], "unique-id-header") == 0) {
5266 if (!*(args[1])) {
5267 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5268 err_code |= ERR_ALERT | ERR_FATAL;
5269 goto out;
5270 }
5271 free(curproxy->header_unique_id);
5272 curproxy->header_unique_id = strdup(args[1]);
5273 }
5274
William Lallemand723b73a2012-02-08 16:37:49 +01005275 else if (strcmp(args[0], "log-format") == 0) {
5276 if (!*(args[1])) {
5277 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5278 err_code |= ERR_ALERT | ERR_FATAL;
5279 goto out;
5280 }
William Lallemand3203ff42012-11-11 17:30:56 +01005281 if (*(args[2])) {
5282 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5283 err_code |= ERR_ALERT | ERR_FATAL;
5284 goto out;
5285 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005286
Willy Tarreau62a61232013-04-12 18:13:46 +02005287 if (curproxy->conf.logformat_string != default_http_log_format &&
5288 curproxy->conf.logformat_string != default_tcp_log_format &&
5289 curproxy->conf.logformat_string != clf_http_log_format)
5290 free(curproxy->conf.logformat_string);
5291 curproxy->conf.logformat_string = strdup(args[1]);
5292
5293 free(curproxy->conf.lfs_file);
5294 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5295 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005296
5297 /* get a chance to improve log-format error reporting by
5298 * reporting the correct line-number when possible.
5299 */
5300 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5301 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5302 file, linenum, curproxy->id);
5303 err_code |= ERR_WARN;
5304 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005306 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5307 if (*(args[1]) == 0) {
5308 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5309 err_code |= ERR_ALERT | ERR_FATAL;
5310 goto out;
5311 }
5312 free(curproxy->log_tag);
5313 curproxy->log_tag = strdup(args[1]);
5314 }
William Lallemand0f99e342011-10-12 17:50:54 +02005315 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5316 /* delete previous herited or defined syslog servers */
5317 struct logsrv *back;
5318
5319 if (*(args[1]) != 0) {
5320 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5321 err_code |= ERR_ALERT | ERR_FATAL;
5322 goto out;
5323 }
5324
William Lallemand723b73a2012-02-08 16:37:49 +01005325 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5326 LIST_DEL(&tmplogsrv->list);
5327 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005328 }
5329 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005330 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005331 struct logsrv *logsrv;
5332
Willy Tarreaubaaee002006-06-26 02:48:02 +02005333 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005334 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005335 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005336 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005337 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005338 LIST_INIT(&node->list);
5339 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5340 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005341 }
5342 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005343 struct sockaddr_storage *sk;
5344 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005345 int arg = 0;
5346 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005347
5348 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005349
Willy Tarreau18324f52014-06-27 18:10:07 +02005350 /* just after the address, a length may be specified */
5351 if (strcmp(args[arg+2], "len") == 0) {
5352 len = atoi(args[arg+3]);
5353 if (len < 80 || len > 65535) {
5354 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5355 file, linenum, args[arg+3]);
5356 err_code |= ERR_ALERT | ERR_FATAL;
5357 goto out;
5358 }
5359 logsrv->maxlen = len;
5360
5361 /* skip these two args */
5362 arg += 2;
5363 }
5364 else
5365 logsrv->maxlen = MAX_SYSLOG_LEN;
5366
5367 if (logsrv->maxlen > global.max_syslog_len) {
5368 global.max_syslog_len = logsrv->maxlen;
5369 logline = realloc(logline, global.max_syslog_len + 1);
5370 }
5371
5372 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005373 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005374 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005375 err_code |= ERR_ALERT | ERR_FATAL;
5376 goto out;
5377
Willy Tarreaubaaee002006-06-26 02:48:02 +02005378 }
5379
William Lallemand0f99e342011-10-12 17:50:54 +02005380 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005381 if (*(args[arg+3])) {
5382 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005383 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005384 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005385 err_code |= ERR_ALERT | ERR_FATAL;
5386 goto out;
5387
Willy Tarreaubaaee002006-06-26 02:48:02 +02005388 }
5389 }
5390
William Lallemand0f99e342011-10-12 17:50:54 +02005391 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005392 if (*(args[arg+4])) {
5393 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005394 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005395 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005396 err_code |= ERR_ALERT | ERR_FATAL;
5397 goto out;
5398
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005399 }
5400 }
5401
Willy Tarreau902636f2013-03-10 19:44:48 +01005402 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005403 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005404 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005405 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005406 goto out;
5407 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005408
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005409 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005410
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005411 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005412 if (port1 != port2) {
5413 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5414 file, linenum, args[0], args[1]);
5415 err_code |= ERR_ALERT | ERR_FATAL;
5416 goto out;
5417 }
5418
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005419 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005420 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005421 }
William Lallemand0f99e342011-10-12 17:50:54 +02005422
5423 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005424 }
5425 else {
5426 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5427 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005428 err_code |= ERR_ALERT | ERR_FATAL;
5429 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005430 }
5431 }
5432 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005433 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005434 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005435 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005436 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005437
Willy Tarreau977b8e42006-12-29 14:19:17 +01005438 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005439 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005440
Willy Tarreaubaaee002006-06-26 02:48:02 +02005441 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005442 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5443 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005444 err_code |= ERR_ALERT | ERR_FATAL;
5445 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005446 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005447
5448 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005449 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5450 free(curproxy->conn_src.iface_name);
5451 curproxy->conn_src.iface_name = NULL;
5452 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005453
Willy Tarreau902636f2013-03-10 19:44:48 +01005454 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005455 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005456 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005457 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005458 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005459 goto out;
5460 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005461
5462 proto = protocol_by_family(sk->ss_family);
5463 if (!proto || !proto->connect) {
5464 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005465 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005466 err_code |= ERR_ALERT | ERR_FATAL;
5467 goto out;
5468 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005469
5470 if (port1 != port2) {
5471 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5472 file, linenum, args[0], args[1]);
5473 err_code |= ERR_ALERT | ERR_FATAL;
5474 goto out;
5475 }
5476
Willy Tarreauef9a3602012-12-08 22:29:20 +01005477 curproxy->conn_src.source_addr = *sk;
5478 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005479
5480 cur_arg = 2;
5481 while (*(args[cur_arg])) {
5482 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005483#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5484#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005485 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005486 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5487 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005488 err_code |= ERR_ALERT | ERR_FATAL;
5489 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005490 }
5491#endif
5492 if (!*args[cur_arg + 1]) {
5493 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5494 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005495 err_code |= ERR_ALERT | ERR_FATAL;
5496 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005497 }
5498
5499 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005500 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5501 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005502 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005503 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5504 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005505 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5506 char *name, *end;
5507
5508 name = args[cur_arg+1] + 7;
5509 while (isspace(*name))
5510 name++;
5511
5512 end = name;
5513 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5514 end++;
5515
Willy Tarreauef9a3602012-12-08 22:29:20 +01005516 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5517 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5518 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5519 curproxy->conn_src.bind_hdr_len = end - name;
5520 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5521 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5522 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005523
5524 /* now look for an occurrence number */
5525 while (isspace(*end))
5526 end++;
5527 if (*end == ',') {
5528 end++;
5529 name = end;
5530 if (*end == '-')
5531 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005532 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005533 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005534 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005535 }
5536
Willy Tarreauef9a3602012-12-08 22:29:20 +01005537 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005538 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5539 " occurrences values smaller than %d.\n",
5540 file, linenum, MAX_HDR_HISTORY);
5541 err_code |= ERR_ALERT | ERR_FATAL;
5542 goto out;
5543 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005544 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005545 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005546
Willy Tarreau902636f2013-03-10 19:44:48 +01005547 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005548 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005549 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005550 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005551 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005552 goto out;
5553 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005554
5555 proto = protocol_by_family(sk->ss_family);
5556 if (!proto || !proto->connect) {
5557 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5558 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005559 err_code |= ERR_ALERT | ERR_FATAL;
5560 goto out;
5561 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005562
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005563 if (port1 != port2) {
5564 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5565 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005566 err_code |= ERR_ALERT | ERR_FATAL;
5567 goto out;
5568 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005569 curproxy->conn_src.tproxy_addr = *sk;
5570 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005571 }
5572 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005573#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005574 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005575#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005576#else /* no TPROXY support */
5577 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005578 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005579 err_code |= ERR_ALERT | ERR_FATAL;
5580 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005581#endif
5582 cur_arg += 2;
5583 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005584 }
5585
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005586 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5587#ifdef SO_BINDTODEVICE
5588 if (!*args[cur_arg + 1]) {
5589 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5590 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005591 err_code |= ERR_ALERT | ERR_FATAL;
5592 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005593 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005594 free(curproxy->conn_src.iface_name);
5595 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5596 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005597 global.last_checks |= LSTCHK_NETADM;
5598#else
5599 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5600 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005601 err_code |= ERR_ALERT | ERR_FATAL;
5602 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005603#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005604 cur_arg += 2;
5605 continue;
5606 }
5607 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005608 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005609 err_code |= ERR_ALERT | ERR_FATAL;
5610 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005612 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005613 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5614 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5615 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005616 err_code |= ERR_ALERT | ERR_FATAL;
5617 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005618 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005619 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005620 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005621 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5622 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005623 err_code |= ERR_ALERT | ERR_FATAL;
5624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005625 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005626
5627 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005628 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005629 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005630 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005631 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005632 }
5633 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005634 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005635 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005636 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005637 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005639 }
5640 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005641 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005642 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005643 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005644 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005645 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005646 }
5647 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005648 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005649 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005650 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005651 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005652 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005653 }
5654 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005655 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005656 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005657 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005658 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005659 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005660 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005661 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005662 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005663 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005664 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005665 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005666 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005667 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005668 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005669 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005670 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005671 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005672 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005673 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005674
5675 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5676 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of the more efficient 'use_backend' which uses a different but more powerful syntax. Future versions will not support '%s' anymore, you should convert it now!\n", file, linenum, args[0], args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01005677 }
5678 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005679 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005680 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005681 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005682 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005683 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005684
5685 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5686 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of the more efficient 'use_backend' which uses a different but more powerful syntax. Future versions will not support '%s' anymore, you should convert it now!\n", file, linenum, args[0], args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01005687 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005688 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005689 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005690 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5691 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005692 err_code |= ERR_ALERT | ERR_FATAL;
5693 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005694 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005695
5696 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005697 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005698 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005699 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005701 }
5702 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005703 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005704 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005705 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005706 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005708 }
5709 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005710 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005711 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005712 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005713 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005715 }
5716 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005717 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005718 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005719 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005720 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005721 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005722 }
5723 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005724 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005725 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005726 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005727 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005729 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005730 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005731 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005732 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005733 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005734 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005735 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005736 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005737 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005738 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005739
Willy Tarreaubaaee002006-06-26 02:48:02 +02005740 if (curproxy == &defproxy) {
5741 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005742 err_code |= ERR_ALERT | ERR_FATAL;
5743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005744 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005745 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005746 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005747
Willy Tarreaubaaee002006-06-26 02:48:02 +02005748 if (*(args[1]) == 0) {
5749 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005750 err_code |= ERR_ALERT | ERR_FATAL;
5751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005752 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005753
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005754 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005755 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5756 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5757 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005758 err_code |= ERR_ALERT | ERR_FATAL;
5759 goto out;
5760 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005761 err_code |= warnif_cond_conflicts(cond,
5762 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5763 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005764 }
5765 else if (*args[2]) {
5766 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5767 file, linenum, args[0], args[2]);
5768 err_code |= ERR_ALERT | ERR_FATAL;
5769 goto out;
5770 }
5771
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005772 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005773 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005774 wl->s = strdup(args[1]);
5775 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005776 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005777 }
5778 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005779 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005780 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5781 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005782 err_code |= ERR_ALERT | ERR_FATAL;
5783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005784 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005785
Willy Tarreauade5ec42010-01-28 19:33:49 +01005786 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005787 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005788 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005789 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005791 }
5792 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005793 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005794 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005795 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005796 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005797 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005798 }
5799 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005800 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005801 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005802 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005803 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005805 }
5806 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005807 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005808 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5809 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005810 err_code |= ERR_ALERT | ERR_FATAL;
5811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005812 }
5813
Willy Tarreauade5ec42010-01-28 19:33:49 +01005814 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005815 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005816 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005817 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005819 }
5820 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005821 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005822 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005823 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005824 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005826 }
5827 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005828 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005829 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005830 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005831 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005833 }
5834 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005835 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005836
Willy Tarreaubaaee002006-06-26 02:48:02 +02005837 if (curproxy == &defproxy) {
5838 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005839 err_code |= ERR_ALERT | ERR_FATAL;
5840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005841 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005842 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005843 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005844
Willy Tarreaubaaee002006-06-26 02:48:02 +02005845 if (*(args[1]) == 0) {
5846 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005847 err_code |= ERR_ALERT | ERR_FATAL;
5848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005849 }
5850
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005851 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005852 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5853 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5854 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005855 err_code |= ERR_ALERT | ERR_FATAL;
5856 goto out;
5857 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005858 err_code |= warnif_cond_conflicts(cond,
5859 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5860 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005861 }
5862 else if (*args[2]) {
5863 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5864 file, linenum, args[0], args[2]);
5865 err_code |= ERR_ALERT | ERR_FATAL;
5866 goto out;
5867 }
5868
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005869 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005870 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005871 wl->s = strdup(args[1]);
5872 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005873 }
5874 else if (!strcmp(args[0], "errorloc") ||
5875 !strcmp(args[0], "errorloc302") ||
5876 !strcmp(args[0], "errorloc303")) { /* error location */
5877 int errnum, errlen;
5878 char *err;
5879
Willy Tarreau977b8e42006-12-29 14:19:17 +01005880 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 Tarreau977b8e42006-12-29 14:19:17 +01005882
Willy Tarreaubaaee002006-06-26 02:48:02 +02005883 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005884 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> 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 Tarreaubaaee002006-06-26 02:48:02 +02005887 }
5888
5889 errnum = atol(args[1]);
5890 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005891 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5892 err = malloc(errlen);
5893 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005894 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005895 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5896 err = malloc(errlen);
5897 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005898 }
5899
Willy Tarreau0f772532006-12-23 20:51:41 +01005900 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5901 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005902 chunk_destroy(&curproxy->errmsg[rc]);
5903 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005904 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005905 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005906 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005907
5908 if (rc >= HTTP_ERR_SIZE) {
5909 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5910 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005911 free(err);
5912 }
5913 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005914 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5915 int errnum, errlen, fd;
5916 char *err;
5917 struct stat stat;
5918
5919 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005920 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005921
5922 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005923 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005924 err_code |= ERR_ALERT | ERR_FATAL;
5925 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005926 }
5927
5928 fd = open(args[2], O_RDONLY);
5929 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5930 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5931 file, linenum, args[2], args[1]);
5932 if (fd >= 0)
5933 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005934 err_code |= ERR_ALERT | ERR_FATAL;
5935 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005936 }
5937
Willy Tarreau27a674e2009-08-17 07:23:33 +02005938 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005939 errlen = stat.st_size;
5940 } else {
5941 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005942 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005943 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005944 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005945 }
5946
5947 err = malloc(errlen); /* malloc() must succeed during parsing */
5948 errnum = read(fd, err, errlen);
5949 if (errnum != errlen) {
5950 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5951 file, linenum, args[2], args[1]);
5952 close(fd);
5953 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005954 err_code |= ERR_ALERT | ERR_FATAL;
5955 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005956 }
5957 close(fd);
5958
5959 errnum = atol(args[1]);
5960 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5961 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005962 chunk_destroy(&curproxy->errmsg[rc]);
5963 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005964 break;
5965 }
5966 }
5967
5968 if (rc >= HTTP_ERR_SIZE) {
5969 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5970 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005971 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005972 free(err);
5973 }
5974 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005975 else if (!strcmp(args[0], "compression")) {
5976 struct comp *comp;
5977 if (curproxy->comp == NULL) {
5978 comp = calloc(1, sizeof(struct comp));
5979 curproxy->comp = comp;
5980 } else {
5981 comp = curproxy->comp;
5982 }
5983
5984 if (!strcmp(args[1], "algo")) {
5985 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005986 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005987
William Lallemand82fe75c2012-10-23 10:25:10 +02005988 cur_arg = 2;
5989 if (!*args[cur_arg]) {
5990 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5991 file, linenum, args[0]);
5992 err_code |= ERR_ALERT | ERR_FATAL;
5993 goto out;
5994 }
5995 while (*(args[cur_arg])) {
5996 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5997 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5998 file, linenum, args[0], args[cur_arg]);
5999 err_code |= ERR_ALERT | ERR_FATAL;
6000 goto out;
6001 }
William Lallemand552df672012-11-07 13:21:47 +01006002 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6003 curproxy->comp->algos->end(&ctx);
6004 } else {
6005 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6006 file, linenum, args[0], args[cur_arg]);
6007 err_code |= ERR_ALERT | ERR_FATAL;
6008 goto out;
6009 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006010 cur_arg ++;
6011 continue;
6012 }
6013 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006014 else if (!strcmp(args[1], "offload")) {
6015 comp->offload = 1;
6016 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006017 else if (!strcmp(args[1], "type")) {
6018 int cur_arg;
6019 cur_arg = 2;
6020 if (!*args[cur_arg]) {
6021 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6022 file, linenum, args[0]);
6023 err_code |= ERR_ALERT | ERR_FATAL;
6024 goto out;
6025 }
6026 while (*(args[cur_arg])) {
6027 comp_append_type(comp, args[cur_arg]);
6028 cur_arg ++;
6029 continue;
6030 }
6031 }
6032 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006033 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006034 file, linenum, args[0]);
6035 err_code |= ERR_ALERT | ERR_FATAL;
6036 goto out;
6037 }
6038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006039 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006040 struct cfg_kw_list *kwl;
6041 int index;
6042
6043 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6044 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6045 if (kwl->kw[index].section != CFG_LISTEN)
6046 continue;
6047 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6048 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006049 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006050 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006051 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006052 err_code |= ERR_ALERT | ERR_FATAL;
6053 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006054 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006055 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006056 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006057 err_code |= ERR_WARN;
6058 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006059 }
Willy Tarreau93893792009-07-23 13:19:11 +02006060 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006061 }
6062 }
6063 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006064
Willy Tarreau6daf3432008-01-22 16:44:08 +01006065 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006066 err_code |= ERR_ALERT | ERR_FATAL;
6067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006068 }
Willy Tarreau93893792009-07-23 13:19:11 +02006069 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006070 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006071 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006072}
6073
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006074int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006075cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6076{
6077#ifdef CONFIG_HAP_NS
6078 const char *err;
6079 const char *item = args[0];
6080
6081 if (!strcmp(item, "namespace_list")) {
6082 return 0;
6083 }
6084 else if (!strcmp(item, "namespace")) {
6085 size_t idx = 1;
6086 const char *current;
6087 while (*(current = args[idx++])) {
6088 err = invalid_char(current);
6089 if (err) {
6090 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6091 file, linenum, *err, item, current);
6092 return ERR_ALERT | ERR_FATAL;
6093 }
6094
6095 if (netns_store_lookup(current, strlen(current))) {
6096 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6097 file, linenum, current);
6098 return ERR_ALERT | ERR_FATAL;
6099 }
6100 if (!netns_store_insert(current)) {
6101 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6102 file, linenum, current);
6103 return ERR_ALERT | ERR_FATAL;
6104 }
6105 }
6106 }
6107
6108 return 0;
6109#else
6110 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6111 file, linenum);
6112 return ERR_ALERT | ERR_FATAL;
6113#endif
6114}
6115
6116int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006117cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6118{
6119
6120 int err_code = 0;
6121 const char *err;
6122
6123 if (!strcmp(args[0], "userlist")) { /* new userlist */
6124 struct userlist *newul;
6125
6126 if (!*args[1]) {
6127 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6128 file, linenum, args[0]);
6129 err_code |= ERR_ALERT | ERR_FATAL;
6130 goto out;
6131 }
6132
6133 err = invalid_char(args[1]);
6134 if (err) {
6135 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6136 file, linenum, *err, args[0], args[1]);
6137 err_code |= ERR_ALERT | ERR_FATAL;
6138 goto out;
6139 }
6140
6141 for (newul = userlist; newul; newul = newul->next)
6142 if (!strcmp(newul->name, args[1])) {
6143 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6144 file, linenum, args[1]);
6145 err_code |= ERR_WARN;
6146 goto out;
6147 }
6148
6149 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6150 if (!newul) {
6151 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6152 err_code |= ERR_ALERT | ERR_ABORT;
6153 goto out;
6154 }
6155
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006156 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006157 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006158 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6159 err_code |= ERR_ALERT | ERR_ABORT;
6160 goto out;
6161 }
6162
6163 newul->next = userlist;
6164 userlist = newul;
6165
6166 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006167 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006168 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006169 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006170
6171 if (!*args[1]) {
6172 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6173 file, linenum, args[0]);
6174 err_code |= ERR_ALERT | ERR_FATAL;
6175 goto out;
6176 }
6177
6178 err = invalid_char(args[1]);
6179 if (err) {
6180 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6181 file, linenum, *err, args[0], args[1]);
6182 err_code |= ERR_ALERT | ERR_FATAL;
6183 goto out;
6184 }
6185
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006186 for (ag = userlist->groups; ag; ag = ag->next)
6187 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006188 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6189 file, linenum, args[1], userlist->name);
6190 err_code |= ERR_ALERT;
6191 goto out;
6192 }
6193
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006194 ag = calloc(1, sizeof(*ag));
6195 if (!ag) {
6196 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6197 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006198 goto out;
6199 }
6200
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006201 ag->name = strdup(args[1]);
6202 if (!ag) {
6203 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6204 err_code |= ERR_ALERT | ERR_ABORT;
6205 goto out;
6206 }
6207
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006208 cur_arg = 2;
6209
6210 while (*args[cur_arg]) {
6211 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006212 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006213 cur_arg += 2;
6214 continue;
6215 } else {
6216 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6217 file, linenum, args[0]);
6218 err_code |= ERR_ALERT | ERR_FATAL;
6219 goto out;
6220 }
6221 }
6222
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006223 ag->next = userlist->groups;
6224 userlist->groups = ag;
6225
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006226 } else if (!strcmp(args[0], "user")) { /* new user */
6227 struct auth_users *newuser;
6228 int cur_arg;
6229
6230 if (!*args[1]) {
6231 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6232 file, linenum, args[0]);
6233 err_code |= ERR_ALERT | ERR_FATAL;
6234 goto out;
6235 }
6236
6237 for (newuser = userlist->users; newuser; newuser = newuser->next)
6238 if (!strcmp(newuser->user, args[1])) {
6239 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6240 file, linenum, args[1], userlist->name);
6241 err_code |= ERR_ALERT;
6242 goto out;
6243 }
6244
6245 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6246 if (!newuser) {
6247 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6248 err_code |= ERR_ALERT | ERR_ABORT;
6249 goto out;
6250 }
6251
6252 newuser->user = strdup(args[1]);
6253
6254 newuser->next = userlist->users;
6255 userlist->users = newuser;
6256
6257 cur_arg = 2;
6258
6259 while (*args[cur_arg]) {
6260 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006261#ifdef CONFIG_HAP_CRYPT
6262 if (!crypt("", args[cur_arg + 1])) {
6263 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6264 file, linenum, newuser->user);
6265 err_code |= ERR_ALERT | ERR_FATAL;
6266 goto out;
6267 }
6268#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006269 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6270 file, linenum);
6271 err_code |= ERR_ALERT;
6272#endif
6273 newuser->pass = strdup(args[cur_arg + 1]);
6274 cur_arg += 2;
6275 continue;
6276 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6277 newuser->pass = strdup(args[cur_arg + 1]);
6278 newuser->flags |= AU_O_INSECURE;
6279 cur_arg += 2;
6280 continue;
6281 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006282 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006283 cur_arg += 2;
6284 continue;
6285 } else {
6286 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6287 file, linenum, args[0]);
6288 err_code |= ERR_ALERT | ERR_FATAL;
6289 goto out;
6290 }
6291 }
6292 } else {
6293 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6294 err_code |= ERR_ALERT | ERR_FATAL;
6295 }
6296
6297out:
6298 return err_code;
6299}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006300
6301/*
6302 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006303 * Returns the error code, 0 if OK, or any combination of :
6304 * - ERR_ABORT: must abort ASAP
6305 * - ERR_FATAL: we can continue parsing but not start the service
6306 * - ERR_WARN: a warning has been emitted
6307 * - ERR_ALERT: an alert has been emitted
6308 * Only the two first ones can stop processing, the two others are just
6309 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006310 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006311int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006312{
William Lallemand64e84512015-05-12 14:25:37 +02006313 char *thisline;
6314 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006315 FILE *f;
6316 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006317 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006318 struct cfg_section *cs = NULL;
6319 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006320 int readbytes = 0;
6321
6322 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006323 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006324 return -1;
6325 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006326
6327 /* Register internal sections */
6328 if (!cfg_register_section("listen", cfg_parse_listen) ||
6329 !cfg_register_section("frontend", cfg_parse_listen) ||
6330 !cfg_register_section("backend", cfg_parse_listen) ||
6331 !cfg_register_section("ruleset", cfg_parse_listen) ||
6332 !cfg_register_section("defaults", cfg_parse_listen) ||
6333 !cfg_register_section("global", cfg_parse_global) ||
6334 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006335 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006336 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006337 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006338 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006339
Willy Tarreaubaaee002006-06-26 02:48:02 +02006340 if ((f=fopen(file,"r")) == NULL)
6341 return -1;
6342
William Lallemandb2f07452015-05-12 14:27:13 +02006343next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006344 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006345 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006346 char *end;
6347 char *args[MAX_LINE_ARGS + 1];
6348 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006349 int dquote = 0; /* double quote */
6350 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006351
Willy Tarreaubaaee002006-06-26 02:48:02 +02006352 linenum++;
6353
6354 end = line + strlen(line);
6355
William Lallemand64e84512015-05-12 14:25:37 +02006356 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006357 /* Check if we reached the limit and the last char is not \n.
6358 * Watch out for the last line without the terminating '\n'!
6359 */
William Lallemand64e84512015-05-12 14:25:37 +02006360 char *newline;
6361 int newlinesize = linesize * 2;
6362
6363 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6364 if (newline == NULL) {
6365 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6366 file, linenum);
6367 err_code |= ERR_ALERT | ERR_FATAL;
6368 continue;
6369 }
6370
6371 readbytes = linesize - 1;
6372 linesize = newlinesize;
6373 thisline = newline;
6374 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006375 }
6376
William Lallemand64e84512015-05-12 14:25:37 +02006377 readbytes = 0;
6378
Willy Tarreaubaaee002006-06-26 02:48:02 +02006379 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006380 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006381 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006382
Willy Tarreaubaaee002006-06-26 02:48:02 +02006383 arg = 0;
6384 args[arg] = line;
6385
6386 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006387 if (*line == '"' && !squote) { /* double quote outside single quotes */
6388 if (dquote)
6389 dquote = 0;
6390 else
6391 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006392 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006393 end--;
6394 }
6395 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6396 if (squote)
6397 squote = 0;
6398 else
6399 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006400 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006401 end--;
6402 }
6403 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006404 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6405 * C equivalent value. Other combinations left unchanged (eg: \1).
6406 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006407 int skip = 0;
6408 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6409 *line = line[1];
6410 skip = 1;
6411 }
6412 else if (line[1] == 'r') {
6413 *line = '\r';
6414 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006415 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006416 else if (line[1] == 'n') {
6417 *line = '\n';
6418 skip = 1;
6419 }
6420 else if (line[1] == 't') {
6421 *line = '\t';
6422 skip = 1;
6423 }
6424 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006425 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006426 unsigned char hex1, hex2;
6427 hex1 = toupper(line[2]) - '0';
6428 hex2 = toupper(line[3]) - '0';
6429 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6430 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6431 *line = (hex1<<4) + hex2;
6432 skip = 3;
6433 }
6434 else {
6435 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006436 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006437 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006438 } else if (line[1] == '"') {
6439 *line = '"';
6440 skip = 1;
6441 } else if (line[1] == '\'') {
6442 *line = '\'';
6443 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006444 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6445 *line = '$';
6446 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006447 }
6448 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006449 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006450 end -= skip;
6451 }
6452 line++;
6453 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006454 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006455 /* end of string, end of loop */
6456 *line = 0;
6457 break;
6458 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006459 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006460 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006461 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006462 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006463 line++;
6464 args[++arg] = line;
6465 }
William Lallemandb2f07452015-05-12 14:27:13 +02006466 else if (dquote && *line == '$') {
6467 /* environment variables are evaluated inside double quotes */
6468 char *var_beg;
6469 char *var_end;
6470 char save_char;
6471 char *value;
6472 int val_len;
6473 int newlinesize;
6474 int braces = 0;
6475
6476 var_beg = line + 1;
6477 var_end = var_beg;
6478
6479 if (*var_beg == '{') {
6480 var_beg++;
6481 var_end++;
6482 braces = 1;
6483 }
6484
6485 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6486 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6487 err_code |= ERR_ALERT | ERR_FATAL;
6488 goto next_line; /* skip current line */
6489 }
6490
6491 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6492 var_end++;
6493
6494 save_char = *var_end;
6495 *var_end = '\0';
6496 value = getenv(var_beg);
6497 *var_end = save_char;
6498 val_len = value ? strlen(value) : 0;
6499
6500 if (braces) {
6501 if (*var_end == '}') {
6502 var_end++;
6503 braces = 0;
6504 } else {
6505 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
6506 err_code |= ERR_ALERT | ERR_FATAL;
6507 goto next_line; /* skip current line */
6508 }
6509 }
6510
6511 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
6512
6513 /* if not enough space in thisline */
6514 if (newlinesize > linesize) {
6515 char *newline;
6516
6517 newline = realloc(thisline, newlinesize * sizeof(*thisline));
6518 if (newline == NULL) {
6519 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
6520 err_code |= ERR_ALERT | ERR_FATAL;
6521 goto next_line; /* slip current line */
6522 }
6523 /* recompute pointers if realloc returns a new pointer */
6524 if (newline != thisline) {
6525 int i;
6526 int diff;
6527
6528 for (i = 0; i <= arg; i++) {
6529 diff = args[i] - thisline;
6530 args[i] = newline + diff;
6531 }
6532
6533 diff = var_end - thisline;
6534 var_end = newline + diff;
6535 diff = end - thisline;
6536 end = newline + diff;
6537 diff = line - thisline;
6538 line = newline + diff;
6539 thisline = newline;
6540 }
6541 linesize = newlinesize;
6542 }
6543
6544 /* insert value inside the line */
6545 memmove(line + val_len, var_end, end - var_end + 1);
6546 memcpy(line, value, val_len);
6547 end += val_len - (var_end - line);
6548 line += val_len;
6549 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006550 else {
6551 line++;
6552 }
6553 }
William Lallemandb2f07452015-05-12 14:27:13 +02006554
William Lallemandf9873ba2015-05-05 17:37:14 +02006555 if (dquote) {
6556 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
6557 err_code |= ERR_ALERT | ERR_FATAL;
6558 }
6559
6560 if (squote) {
6561 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
6562 err_code |= ERR_ALERT | ERR_FATAL;
6563 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006564
6565 /* empty line */
6566 if (!**args)
6567 continue;
6568
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006569 if (*line) {
6570 /* we had to stop due to too many args.
6571 * Let's terminate the string, print the offending part then cut the
6572 * last arg.
6573 */
6574 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6575 line++;
6576 *line = '\0';
6577
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006578 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006579 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006580 err_code |= ERR_ALERT | ERR_FATAL;
6581 args[arg] = line;
6582 }
6583
Willy Tarreau540abe42007-05-02 20:50:16 +02006584 /* zero out remaining args and ensure that at least one entry
6585 * is zeroed out.
6586 */
6587 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006588 args[arg] = line;
6589 }
6590
Willy Tarreau3842f002009-06-14 11:39:52 +02006591 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006592 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006593 char *tmp;
6594
Willy Tarreau3842f002009-06-14 11:39:52 +02006595 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006596 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006597 for (arg=0; *args[arg+1]; arg++)
6598 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006599 *tmp = '\0'; // fix the next arg to \0
6600 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006601 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006602 else if (!strcmp(args[0], "default")) {
6603 kwm = KWM_DEF;
6604 for (arg=0; *args[arg+1]; arg++)
6605 args[arg] = args[arg+1]; // shift args after inversion
6606 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006607
William Lallemand0f99e342011-10-12 17:50:54 +02006608 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6609 strcmp(args[0], "log") != 0) {
6610 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006611 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006612 }
6613
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006614 /* detect section start */
6615 list_for_each_entry(ics, &sections, list) {
6616 if (strcmp(args[0], ics->section_name) == 0) {
6617 cursection = ics->section_name;
6618 cs = ics;
6619 break;
6620 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006621 }
6622
Willy Tarreaubaaee002006-06-26 02:48:02 +02006623 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006624 if (cs)
6625 err_code |= cs->section_parser(file, linenum, args, kwm);
6626 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006627 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006628 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006629 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006630
6631 if (err_code & ERR_ABORT)
6632 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006633 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006634 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02006635 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006636 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006637 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006638}
6639
Willy Tarreau64ab6072014-09-16 12:17:36 +02006640/* This function propagates processes from frontend <from> to backend <to> so
6641 * that it is always guaranteed that a backend pointed to by a frontend is
6642 * bound to all of its processes. After that, if the target is a "listen"
6643 * instance, the function recursively descends the target's own targets along
6644 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6645 * checked first to ensure that <to> is already bound to all processes of
6646 * <from>, there is no risk of looping and we ensure to follow the shortest
6647 * path to the destination.
6648 *
6649 * It is possible to set <to> to NULL for the first call so that the function
6650 * takes care of visiting the initial frontend in <from>.
6651 *
6652 * It is important to note that the function relies on the fact that all names
6653 * have already been resolved.
6654 */
6655void propagate_processes(struct proxy *from, struct proxy *to)
6656{
6657 struct switching_rule *rule;
6658 struct hdr_exp *exp;
6659
6660 if (to) {
6661 /* check whether we need to go down */
6662 if (from->bind_proc &&
6663 (from->bind_proc & to->bind_proc) == from->bind_proc)
6664 return;
6665
6666 if (!from->bind_proc && !to->bind_proc)
6667 return;
6668
6669 to->bind_proc = from->bind_proc ?
6670 (to->bind_proc | from->bind_proc) : 0;
6671
6672 /* now propagate down */
6673 from = to;
6674 }
6675
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006676 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006677 return;
6678
Willy Tarreauf6b70012014-12-18 14:00:43 +01006679 if (from->state == PR_STSTOPPED)
6680 return;
6681
Willy Tarreau64ab6072014-09-16 12:17:36 +02006682 /* default_backend */
6683 if (from->defbe.be)
6684 propagate_processes(from, from->defbe.be);
6685
6686 /* use_backend */
6687 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006688 if (rule->dynamic)
6689 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006690 to = rule->be.backend;
6691 propagate_processes(from, to);
6692 }
6693
6694 /* reqsetbe */
6695 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6696 if (exp->action != ACT_SETBE)
6697 continue;
6698 to = (struct proxy *)exp->replace;
6699 propagate_processes(from, to);
6700 }
6701}
6702
Willy Tarreaubb925012009-07-23 13:36:36 +02006703/*
6704 * Returns the error code, 0 if OK, or any combination of :
6705 * - ERR_ABORT: must abort ASAP
6706 * - ERR_FATAL: we can continue parsing but not start the service
6707 * - ERR_WARN: a warning has been emitted
6708 * - ERR_ALERT: an alert has been emitted
6709 * Only the two first ones can stop processing, the two others are just
6710 * indicators.
6711 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006712int check_config_validity()
6713{
6714 int cfgerr = 0;
6715 struct proxy *curproxy = NULL;
6716 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006717 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006718 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006719 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006720
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006721 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006722 /*
6723 * Now, check for the integrity of all that we have collected.
6724 */
6725
6726 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006727 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006728
Willy Tarreau193b8c62012-11-22 00:17:38 +01006729 if (!global.tune.max_http_hdr)
6730 global.tune.max_http_hdr = MAX_HTTP_HDR;
6731
6732 if (!global.tune.cookie_len)
6733 global.tune.cookie_len = CAPTURE_LEN;
6734
6735 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6736
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006737 /* Post initialisation of the users and groups lists. */
6738 err_code = userlist_postinit();
6739 if (err_code != ERR_NONE)
6740 goto out;
6741
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006742 /* first, we will invert the proxy list order */
6743 curproxy = NULL;
6744 while (proxy) {
6745 struct proxy *next;
6746
6747 next = proxy->next;
6748 proxy->next = curproxy;
6749 curproxy = proxy;
6750 if (!next)
6751 break;
6752 proxy = next;
6753 }
6754
Willy Tarreau419ead82014-09-16 13:41:21 +02006755 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006756 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006757 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006758 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006759 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006760 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006761 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006762 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006763
Willy Tarreau050536d2012-10-04 08:47:34 +02006764 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006765 /* proxy ID not set, use automatic numbering with first
6766 * spare entry starting with next_pxid.
6767 */
6768 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6769 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6770 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006771 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006772 next_pxid++;
6773
Willy Tarreau55ea7572007-06-17 19:56:27 +02006774
Willy Tarreaubaaee002006-06-26 02:48:02 +02006775 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006776 /* ensure we don't keep listeners uselessly bound */
6777 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02006778 free((void *)curproxy->table.peers.name);
6779 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006780 continue;
6781 }
6782
Willy Tarreau102df612014-05-07 23:56:38 +02006783 /* Check multi-process mode compatibility for the current proxy */
6784
6785 if (curproxy->bind_proc) {
6786 /* an explicit bind-process was specified, let's check how many
6787 * processes remain.
6788 */
6789 nbproc = popcount(curproxy->bind_proc);
6790
6791 curproxy->bind_proc &= nbits(global.nbproc);
6792 if (!curproxy->bind_proc && nbproc == 1) {
6793 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);
6794 curproxy->bind_proc = 1;
6795 }
6796 else if (!curproxy->bind_proc && nbproc > 1) {
6797 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);
6798 curproxy->bind_proc = 0;
6799 }
6800 }
6801
Willy Tarreau3d209582014-05-09 17:06:11 +02006802 /* check and reduce the bind-proc of each listener */
6803 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6804 unsigned long mask;
6805
6806 if (!bind_conf->bind_proc)
6807 continue;
6808
6809 mask = nbits(global.nbproc);
6810 if (curproxy->bind_proc)
6811 mask &= curproxy->bind_proc;
6812 /* mask cannot be null here thanks to the previous checks */
6813
6814 nbproc = popcount(bind_conf->bind_proc);
6815 bind_conf->bind_proc &= mask;
6816
6817 if (!bind_conf->bind_proc && nbproc == 1) {
6818 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",
6819 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6820 bind_conf->bind_proc = mask & ~(mask - 1);
6821 }
6822 else if (!bind_conf->bind_proc && nbproc > 1) {
6823 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",
6824 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6825 bind_conf->bind_proc = 0;
6826 }
6827 }
6828
Willy Tarreauff01a212009-03-15 13:46:16 +01006829 switch (curproxy->mode) {
6830 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006831 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006832 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006833 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6834 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006835 cfgerr++;
6836 }
6837
6838 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006839 Warning("config : servers will be ignored for %s '%s'.\n",
6840 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006841 break;
6842
6843 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006844 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006845 break;
6846
6847 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006848 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006849 break;
6850 }
6851
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006852 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006853 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006854 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006855 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6856 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006857 cfgerr++;
6858 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006859#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006860 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006861 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6862 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006863 cfgerr++;
6864 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006865#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006866 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006867 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6868 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006869 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006870 }
6871 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006872 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006873 /* If no LB algo is set in a backend, and we're not in
6874 * transparent mode, dispatch mode nor proxy mode, we
6875 * want to use balance roundrobin by default.
6876 */
6877 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6878 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006879 }
6880 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006881
Willy Tarreau1620ec32011-08-06 17:05:02 +02006882 if (curproxy->options & PR_O_DISPATCH)
6883 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6884 else if (curproxy->options & PR_O_HTTP_PROXY)
6885 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6886 else if (curproxy->options & PR_O_TRANSP)
6887 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006888
Willy Tarreau1620ec32011-08-06 17:05:02 +02006889 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6890 if (curproxy->options & PR_O_DISABLE404) {
6891 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6892 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6893 err_code |= ERR_WARN;
6894 curproxy->options &= ~PR_O_DISABLE404;
6895 }
6896 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6897 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6898 "send-state", proxy_type_str(curproxy), curproxy->id);
6899 err_code |= ERR_WARN;
6900 curproxy->options &= ~PR_O2_CHK_SNDST;
6901 }
Willy Tarreauef781042010-01-27 11:53:01 +01006902 }
6903
Simon Horman98637e52014-06-20 12:30:16 +09006904 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6905 if (!global.external_check) {
6906 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6907 curproxy->id, "option external-check");
6908 cfgerr++;
6909 }
6910 if (!curproxy->check_command) {
6911 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6912 curproxy->id, "option external-check");
6913 cfgerr++;
6914 }
6915 }
6916
Simon Horman64e34162015-02-06 11:11:57 +09006917 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006918 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
6919 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09006920 "'email-alert from', 'email-alert level' 'email-alert mailer', "
6921 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006922 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
6923 "to be present).\n",
6924 proxy_type_str(curproxy), curproxy->id);
6925 err_code |= ERR_WARN;
6926 free_email_alert(curproxy);
6927 }
6928 if (!curproxy->email_alert.myhostname)
6929 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09006930 }
6931
Simon Horman98637e52014-06-20 12:30:16 +09006932 if (curproxy->check_command) {
6933 int clear = 0;
6934 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6935 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6936 "external-check command", proxy_type_str(curproxy), curproxy->id);
6937 err_code |= ERR_WARN;
6938 clear = 1;
6939 }
6940 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6941 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6942 curproxy->id, "external-check command");
6943 cfgerr++;
6944 }
6945 if (clear) {
6946 free(curproxy->check_command);
6947 curproxy->check_command = NULL;
6948 }
6949 }
6950
6951 if (curproxy->check_path) {
6952 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6953 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6954 "external-check path", proxy_type_str(curproxy), curproxy->id);
6955 err_code |= ERR_WARN;
6956 free(curproxy->check_path);
6957 curproxy->check_path = NULL;
6958 }
6959 }
6960
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006961 /* if a default backend was specified, let's find it */
6962 if (curproxy->defbe.name) {
6963 struct proxy *target;
6964
Alex Williams96532db2009-11-01 21:27:13 -05006965 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006966 if (!target) {
6967 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6968 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006969 cfgerr++;
6970 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006971 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6972 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006973 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006974 } else {
6975 free(curproxy->defbe.name);
6976 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006977
6978 /* Emit a warning if this proxy also has some servers */
6979 if (curproxy->srv) {
6980 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6981 curproxy->id);
6982 err_code |= ERR_WARN;
6983 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006984 }
6985 }
6986
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006987 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006988 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6989 /* map jump target for ACT_SETBE in req_rep chain */
6990 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006991 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006992 struct proxy *target;
6993
Willy Tarreaua496b602006-12-17 23:15:24 +01006994 if (exp->action != ACT_SETBE)
6995 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006996
Alex Williams96532db2009-11-01 21:27:13 -05006997 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006998 if (!target) {
6999 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
7000 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01007001 cfgerr++;
7002 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007003 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
7004 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01007005 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01007006 } else {
7007 free((void *)exp->replace);
7008 exp->replace = (const char *)target;
7009 }
7010 }
7011 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007012
7013 /* find the target proxy for 'use_backend' rules */
7014 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007015 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007016 struct logformat_node *node;
7017 char *pxname;
7018
7019 /* Try to parse the string as a log format expression. If the result
7020 * of the parsing is only one entry containing a simple string, then
7021 * it's a standard string corresponding to a static rule, thus the
7022 * parsing is cancelled and be.name is restored to be resolved.
7023 */
7024 pxname = rule->be.name;
7025 LIST_INIT(&rule->be.expr);
7026 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7027 curproxy->conf.args.file, curproxy->conf.args.line);
7028 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7029
7030 if (!LIST_ISEMPTY(&rule->be.expr)) {
7031 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7032 rule->dynamic = 1;
7033 free(pxname);
7034 continue;
7035 }
7036 /* simple string: free the expression and fall back to static rule */
7037 free(node->arg);
7038 free(node);
7039 }
7040
7041 rule->dynamic = 0;
7042 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007043
Alex Williams96532db2009-11-01 21:27:13 -05007044 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007045
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007046 if (!target) {
7047 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7048 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007049 cfgerr++;
7050 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007051 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7052 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007053 cfgerr++;
7054 } else {
7055 free((void *)rule->be.name);
7056 rule->be.backend = target;
7057 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007058 }
7059
Willy Tarreau64ab6072014-09-16 12:17:36 +02007060 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007061 list_for_each_entry(srule, &curproxy->server_rules, list) {
7062 struct server *target = findserver(curproxy, srule->srv.name);
7063
7064 if (!target) {
7065 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7066 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7067 cfgerr++;
7068 continue;
7069 }
7070 free((void *)srule->srv.name);
7071 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007072 }
7073
Emeric Brunb982a3d2010-01-04 15:45:53 +01007074 /* find the target table for 'stick' rules */
7075 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7076 struct proxy *target;
7077
Emeric Brun1d33b292010-01-04 15:47:17 +01007078 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7079 if (mrule->flags & STK_IS_STORE)
7080 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7081
Emeric Brunb982a3d2010-01-04 15:45:53 +01007082 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007083 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007084 else
7085 target = curproxy;
7086
7087 if (!target) {
7088 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7089 curproxy->id, mrule->table.name);
7090 cfgerr++;
7091 }
7092 else if (target->table.size == 0) {
7093 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7094 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7095 cfgerr++;
7096 }
Willy Tarreau12785782012-04-27 21:37:17 +02007097 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7098 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007099 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7100 cfgerr++;
7101 }
7102 else {
7103 free((void *)mrule->table.name);
7104 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007105 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007106 }
7107 }
7108
7109 /* find the target table for 'store response' rules */
7110 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7111 struct proxy *target;
7112
Emeric Brun1d33b292010-01-04 15:47:17 +01007113 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7114
Emeric Brunb982a3d2010-01-04 15:45:53 +01007115 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007116 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007117 else
7118 target = curproxy;
7119
7120 if (!target) {
7121 Alert("Proxy '%s': unable to find store table '%s'.\n",
7122 curproxy->id, mrule->table.name);
7123 cfgerr++;
7124 }
7125 else if (target->table.size == 0) {
7126 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7127 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7128 cfgerr++;
7129 }
Willy Tarreau12785782012-04-27 21:37:17 +02007130 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7131 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007132 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7133 cfgerr++;
7134 }
7135 else {
7136 free((void *)mrule->table.name);
7137 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007138 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007139 }
7140 }
7141
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007142 /* find the target table for 'tcp-request' layer 4 rules */
7143 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7144 struct proxy *target;
7145
Willy Tarreaub4c84932013-07-23 19:15:30 +02007146 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007147 continue;
7148
7149 if (trule->act_prm.trk_ctr.table.n)
7150 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
7151 else
7152 target = curproxy;
7153
7154 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007155 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7156 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007157 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007158 cfgerr++;
7159 }
7160 else if (target->table.size == 0) {
7161 Alert("Proxy '%s': table '%s' used but not configured.\n",
7162 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7163 cfgerr++;
7164 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007165 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7166 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7167 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 +01007168 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007169 cfgerr++;
7170 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007171 else {
7172 free(trule->act_prm.trk_ctr.table.n);
7173 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007174 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007175 * to pass a list of counters to track and allocate them right here using
7176 * stktable_alloc_data_type().
7177 */
7178 }
7179 }
7180
Willy Tarreaud1f96522010-08-03 19:34:32 +02007181 /* find the target table for 'tcp-request' layer 6 rules */
7182 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7183 struct proxy *target;
7184
Willy Tarreaub4c84932013-07-23 19:15:30 +02007185 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007186 continue;
7187
7188 if (trule->act_prm.trk_ctr.table.n)
7189 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
7190 else
7191 target = curproxy;
7192
7193 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007194 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7195 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007196 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007197 cfgerr++;
7198 }
7199 else if (target->table.size == 0) {
7200 Alert("Proxy '%s': table '%s' used but not configured.\n",
7201 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7202 cfgerr++;
7203 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007204 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7205 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7206 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 +01007207 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007208 cfgerr++;
7209 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007210 else {
7211 free(trule->act_prm.trk_ctr.table.n);
7212 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007213 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007214 * to pass a list of counters to track and allocate them right here using
7215 * stktable_alloc_data_type().
7216 */
7217 }
7218 }
7219
Willy Tarreau09448f72014-06-25 18:12:15 +02007220 /* find the target table for 'http-request' layer 7 rules */
7221 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7222 struct proxy *target;
7223
7224 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
7225 continue;
7226
7227 if (hrqrule->act_prm.trk_ctr.table.n)
7228 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
7229 else
7230 target = curproxy;
7231
7232 if (!target) {
7233 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7234 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
7235 http_req_trk_idx(hrqrule->action));
7236 cfgerr++;
7237 }
7238 else if (target->table.size == 0) {
7239 Alert("Proxy '%s': table '%s' used but not configured.\n",
7240 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
7241 cfgerr++;
7242 }
7243 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
7244 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7245 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
7246 http_req_trk_idx(hrqrule->action));
7247 cfgerr++;
7248 }
7249 else {
7250 free(hrqrule->act_prm.trk_ctr.table.n);
7251 hrqrule->act_prm.trk_ctr.table.t = &target->table;
7252 /* Note: if we decide to enhance the track-sc syntax, we may be able
7253 * to pass a list of counters to track and allocate them right here using
7254 * stktable_alloc_data_type().
7255 */
7256 }
7257 }
7258
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007259 /* move any "block" rules at the beginning of the http-request rules */
7260 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7261 /* insert block_rules into http_req_rules at the beginning */
7262 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7263 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7264 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7265 curproxy->http_req_rules.n = curproxy->block_rules.n;
7266 LIST_INIT(&curproxy->block_rules);
7267 }
7268
Emeric Brun32da3c42010-09-23 18:39:19 +02007269 if (curproxy->table.peers.name) {
7270 struct peers *curpeers = peers;
7271
7272 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7273 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7274 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007275 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007276 break;
7277 }
7278 }
7279
7280 if (!curpeers) {
7281 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7282 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007283 free((void *)curproxy->table.peers.name);
7284 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007285 cfgerr++;
7286 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007287 else if (curpeers->state == PR_STSTOPPED) {
7288 /* silently disable this peers section */
7289 curproxy->table.peers.p = NULL;
7290 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007291 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007292 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7293 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007294 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007295 cfgerr++;
7296 }
7297 }
7298
Simon Horman9dc49962015-01-30 11:22:59 +09007299
7300 if (curproxy->email_alert.mailers.name) {
7301 struct mailers *curmailers = mailers;
7302
7303 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7304 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7305 free(curproxy->email_alert.mailers.name);
7306 curproxy->email_alert.mailers.m = curmailers;
7307 curmailers->users++;
7308 break;
7309 }
7310 }
7311
7312 if (!curmailers) {
7313 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7314 curproxy->id, curproxy->email_alert.mailers.name);
7315 free_email_alert(curproxy);
7316 cfgerr++;
7317 }
7318 }
7319
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007320 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007321 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007322 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7323 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7324 "proxy", curproxy->id);
7325 cfgerr++;
7326 goto out_uri_auth_compat;
7327 }
7328
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007329 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007330 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007331 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007332 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007333
Willy Tarreau95fa4692010-02-01 13:05:50 +01007334 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7335 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007336
7337 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007338 uri_auth_compat_req[i++] = "realm";
7339 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7340 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007341
Willy Tarreau95fa4692010-02-01 13:05:50 +01007342 uri_auth_compat_req[i++] = "unless";
7343 uri_auth_compat_req[i++] = "{";
7344 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7345 uri_auth_compat_req[i++] = "}";
7346 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007347
Willy Tarreauff011f22011-01-06 17:51:27 +01007348 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7349 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007350 cfgerr++;
7351 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007352 }
7353
Willy Tarreauff011f22011-01-06 17:51:27 +01007354 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007355
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007356 if (curproxy->uri_auth->auth_realm) {
7357 free(curproxy->uri_auth->auth_realm);
7358 curproxy->uri_auth->auth_realm = NULL;
7359 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007360
7361 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007362 }
7363out_uri_auth_compat:
7364
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007365 /* compile the log format */
7366 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007367 if (curproxy->conf.logformat_string != default_http_log_format &&
7368 curproxy->conf.logformat_string != default_tcp_log_format &&
7369 curproxy->conf.logformat_string != clf_http_log_format)
7370 free(curproxy->conf.logformat_string);
7371 curproxy->conf.logformat_string = NULL;
7372 free(curproxy->conf.lfs_file);
7373 curproxy->conf.lfs_file = NULL;
7374 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007375 }
7376
Willy Tarreau62a61232013-04-12 18:13:46 +02007377 if (curproxy->conf.logformat_string) {
7378 curproxy->conf.args.ctx = ARGC_LOG;
7379 curproxy->conf.args.file = curproxy->conf.lfs_file;
7380 curproxy->conf.args.line = curproxy->conf.lfs_line;
7381 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007382 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007383 curproxy->conf.args.file = NULL;
7384 curproxy->conf.args.line = 0;
7385 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007386
Willy Tarreau62a61232013-04-12 18:13:46 +02007387 if (curproxy->conf.uniqueid_format_string) {
7388 curproxy->conf.args.ctx = ARGC_UIF;
7389 curproxy->conf.args.file = curproxy->conf.uif_file;
7390 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007391 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007392 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007393 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007394 curproxy->conf.args.file = NULL;
7395 curproxy->conf.args.line = 0;
7396 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007397
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007398 /* only now we can check if some args remain unresolved.
7399 * This must be done after the users and groups resolution.
7400 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007401 cfgerr += smp_resolve_args(curproxy);
7402 if (!cfgerr)
7403 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007404
Willy Tarreau2738a142006-07-08 17:28:09 +02007405 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007406 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007407 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007408 (!curproxy->timeout.connect ||
7409 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007410 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007411 " | While not properly invalid, you will certainly encounter various problems\n"
7412 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007413 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007414 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007415 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007416 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007417
Willy Tarreau1fa31262007-12-03 00:36:16 +01007418 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7419 * We must still support older configurations, so let's find out whether those
7420 * parameters have been set or must be copied from contimeouts.
7421 */
7422 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007423 if (!curproxy->timeout.tarpit ||
7424 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007425 /* tarpit timeout not set. We search in the following order:
7426 * default.tarpit, curr.connect, default.connect.
7427 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007428 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007429 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007430 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007431 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007432 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007433 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007434 }
7435 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007436 (!curproxy->timeout.queue ||
7437 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007438 /* queue timeout not set. We search in the following order:
7439 * default.queue, curr.connect, default.connect.
7440 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007441 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007442 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007443 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007444 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007445 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007446 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007447 }
7448 }
7449
Willy Tarreau1620ec32011-08-06 17:05:02 +02007450 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007451 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7452 curproxy->check_req = (char *)malloc(curproxy->check_len);
7453 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007454 }
7455
Willy Tarreau215663d2014-06-13 18:30:23 +02007456 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7457 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7458 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7459 proxy_type_str(curproxy), curproxy->id);
7460 err_code |= ERR_WARN;
7461 }
7462
Willy Tarreau193b8c62012-11-22 00:17:38 +01007463 /* ensure that cookie capture length is not too large */
7464 if (curproxy->capture_len >= global.tune.cookie_len) {
7465 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7466 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7467 err_code |= ERR_WARN;
7468 curproxy->capture_len = global.tune.cookie_len - 1;
7469 }
7470
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007471 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007472 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007473 curproxy->req_cap_pool = create_pool("ptrcap",
7474 curproxy->nb_req_cap * sizeof(char *),
7475 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007476 }
7477
7478 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007479 curproxy->rsp_cap_pool = create_pool("ptrcap",
7480 curproxy->nb_rsp_cap * sizeof(char *),
7481 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007482 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007483
Willy Tarreaubaaee002006-06-26 02:48:02 +02007484 /* first, we will invert the servers list order */
7485 newsrv = NULL;
7486 while (curproxy->srv) {
7487 struct server *next;
7488
7489 next = curproxy->srv->next;
7490 curproxy->srv->next = newsrv;
7491 newsrv = curproxy->srv;
7492 if (!next)
7493 break;
7494 curproxy->srv = next;
7495 }
7496
Willy Tarreau17edc812014-01-03 12:14:34 +01007497 /* Check that no server name conflicts. This causes trouble in the stats.
7498 * We only emit a warning for the first conflict affecting each server,
7499 * in order to avoid combinatory explosion if all servers have the same
7500 * name. We do that only for servers which do not have an explicit ID,
7501 * because these IDs were made also for distinguishing them and we don't
7502 * want to annoy people who correctly manage them.
7503 */
7504 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7505 struct server *other_srv;
7506
7507 if (newsrv->puid)
7508 continue;
7509
7510 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7511 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7512 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7513 newsrv->conf.file, newsrv->conf.line,
7514 proxy_type_str(curproxy), curproxy->id,
7515 newsrv->id, other_srv->conf.line);
7516 break;
7517 }
7518 }
7519 }
7520
Willy Tarreaudd701652010-05-25 23:03:02 +02007521 /* assign automatic UIDs to servers which don't have one yet */
7522 next_id = 1;
7523 newsrv = curproxy->srv;
7524 while (newsrv != NULL) {
7525 if (!newsrv->puid) {
7526 /* server ID not set, use automatic numbering with first
7527 * spare entry starting with next_svid.
7528 */
7529 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7530 newsrv->conf.id.key = newsrv->puid = next_id;
7531 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7532 }
7533 next_id++;
7534 newsrv = newsrv->next;
7535 }
7536
Willy Tarreau20697042007-11-15 23:26:18 +01007537 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007538 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007539
Willy Tarreau62c3be22012-01-20 13:12:32 +01007540 /*
7541 * If this server supports a maxconn parameter, it needs a dedicated
7542 * tasks to fill the emptied slots when a connection leaves.
7543 * Also, resolve deferred tracking dependency if needed.
7544 */
7545 newsrv = curproxy->srv;
7546 while (newsrv != NULL) {
7547 if (newsrv->minconn > newsrv->maxconn) {
7548 /* Only 'minconn' was specified, or it was higher than or equal
7549 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7550 * this will avoid further useless expensive computations.
7551 */
7552 newsrv->maxconn = newsrv->minconn;
7553 } else if (newsrv->maxconn && !newsrv->minconn) {
7554 /* minconn was not specified, so we set it to maxconn */
7555 newsrv->minconn = newsrv->maxconn;
7556 }
7557
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007558#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007559 if (newsrv->use_ssl || newsrv->check.use_ssl)
7560 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007561#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007562
Willy Tarreau2f075e92013-12-03 11:11:34 +01007563 /* set the check type on the server */
7564 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7565
Willy Tarreau62c3be22012-01-20 13:12:32 +01007566 if (newsrv->trackit) {
7567 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007568 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007569 char *pname, *sname;
7570
7571 pname = newsrv->trackit;
7572 sname = strrchr(pname, '/');
7573
7574 if (sname)
7575 *sname++ = '\0';
7576 else {
7577 sname = pname;
7578 pname = NULL;
7579 }
7580
7581 if (pname) {
7582 px = findproxy(pname, PR_CAP_BE);
7583 if (!px) {
7584 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7585 proxy_type_str(curproxy), curproxy->id,
7586 newsrv->id, pname);
7587 cfgerr++;
7588 goto next_srv;
7589 }
7590 } else
7591 px = curproxy;
7592
7593 srv = findserver(px, sname);
7594 if (!srv) {
7595 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7596 proxy_type_str(curproxy), curproxy->id,
7597 newsrv->id, sname);
7598 cfgerr++;
7599 goto next_srv;
7600 }
7601
Willy Tarreau32091232014-05-16 13:52:00 +02007602 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7603 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7604 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007605 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007606 "tracking as it does not have any check nor agent enabled.\n",
7607 proxy_type_str(curproxy), curproxy->id,
7608 newsrv->id, px->id, srv->id);
7609 cfgerr++;
7610 goto next_srv;
7611 }
7612
7613 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7614
7615 if (loop) {
7616 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7617 "belongs to a tracking chain looping back to %s/%s.\n",
7618 proxy_type_str(curproxy), curproxy->id,
7619 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007620 cfgerr++;
7621 goto next_srv;
7622 }
7623
7624 if (curproxy != px &&
7625 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7626 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7627 "tracking: disable-on-404 option inconsistency.\n",
7628 proxy_type_str(curproxy), curproxy->id,
7629 newsrv->id, px->id, srv->id);
7630 cfgerr++;
7631 goto next_srv;
7632 }
7633
7634 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007635 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007636 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007637 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007638 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007639 }
7640
7641 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007642 newsrv->tracknext = srv->trackers;
7643 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007644
7645 free(newsrv->trackit);
7646 newsrv->trackit = NULL;
7647 }
7648 next_srv:
7649 newsrv = newsrv->next;
7650 }
7651
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007652 /* We have to initialize the server lookup mechanism depending
7653 * on what LB algorithm was choosen.
7654 */
7655
7656 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7657 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7658 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007659 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7660 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7661 init_server_map(curproxy);
7662 } else {
7663 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7664 fwrr_init_server_groups(curproxy);
7665 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007666 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007667
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007668 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007669 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7670 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7671 fwlc_init_server_tree(curproxy);
7672 } else {
7673 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7674 fas_init_server_tree(curproxy);
7675 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007676 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007677
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007678 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007679 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7680 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7681 chash_init_server_tree(curproxy);
7682 } else {
7683 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7684 init_server_map(curproxy);
7685 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007686 break;
7687 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007688
7689 if (curproxy->options & PR_O_LOGASAP)
7690 curproxy->to_log &= ~LW_BYTES;
7691
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007692 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007693 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007694 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7695 proxy_type_str(curproxy), curproxy->id);
7696 err_code |= ERR_WARN;
7697 }
7698
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007699 if (curproxy->mode != PR_MODE_HTTP) {
7700 int optnum;
7701
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007702 if (curproxy->uri_auth) {
7703 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7704 proxy_type_str(curproxy), curproxy->id);
7705 err_code |= ERR_WARN;
7706 curproxy->uri_auth = NULL;
7707 }
7708
Willy Tarreau87cf5142011-08-19 22:57:24 +02007709 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007710 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7711 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7712 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007713 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007714 }
7715
7716 if (curproxy->options & PR_O_ORGTO) {
7717 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7718 "originalto", proxy_type_str(curproxy), curproxy->id);
7719 err_code |= ERR_WARN;
7720 curproxy->options &= ~PR_O_ORGTO;
7721 }
7722
7723 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7724 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7725 (curproxy->cap & cfg_opts[optnum].cap) &&
7726 (curproxy->options & cfg_opts[optnum].val)) {
7727 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7728 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7729 err_code |= ERR_WARN;
7730 curproxy->options &= ~cfg_opts[optnum].val;
7731 }
7732 }
7733
7734 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7735 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7736 (curproxy->cap & cfg_opts2[optnum].cap) &&
7737 (curproxy->options2 & cfg_opts2[optnum].val)) {
7738 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7739 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7740 err_code |= ERR_WARN;
7741 curproxy->options2 &= ~cfg_opts2[optnum].val;
7742 }
7743 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007744
Pieter Baauwd551fb52013-05-08 22:49:23 +02007745#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007746 if (curproxy->conn_src.bind_hdr_occ) {
7747 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007748 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007749 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007750 err_code |= ERR_WARN;
7751 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007752#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007753 }
7754
Willy Tarreaubaaee002006-06-26 02:48:02 +02007755 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007756 * ensure that we're not cross-dressing a TCP server into HTTP.
7757 */
7758 newsrv = curproxy->srv;
7759 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007760 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007761 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7762 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007763 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007764 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007765
Willy Tarreau0cec3312011-10-31 13:49:26 +01007766 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7767 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7768 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7769 err_code |= ERR_WARN;
7770 }
7771
Willy Tarreauc93cd162014-05-13 15:54:22 +02007772 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007773 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7774 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7775 err_code |= ERR_WARN;
7776 }
7777
Pieter Baauwd551fb52013-05-08 22:49:23 +02007778#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007779 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7780 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007781 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 +01007782 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007783 err_code |= ERR_WARN;
7784 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007785#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007786 newsrv = newsrv->next;
7787 }
7788
Willy Tarreaue42bd962014-09-16 16:21:19 +02007789 /* check if we have a frontend with "tcp-request content" looking at L7
7790 * with no inspect-delay
7791 */
7792 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7793 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7794 if (trule->action == TCP_ACT_CAPTURE &&
7795 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7796 break;
7797 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7798 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7799 break;
7800 }
7801
7802 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7803 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7804 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7805 " This means that these rules will randomly find their contents. This can be fixed by"
7806 " setting the tcp-request inspect-delay.\n",
7807 proxy_type_str(curproxy), curproxy->id);
7808 err_code |= ERR_WARN;
7809 }
7810 }
7811
Willy Tarreauc1a21672009-08-16 22:37:44 +02007812 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007813 if (!curproxy->accept)
7814 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007815
Willy Tarreauc1a21672009-08-16 22:37:44 +02007816 if (curproxy->tcp_req.inspect_delay ||
7817 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007818 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007819
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007820 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007821 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007822 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007823 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007824
7825 /* both TCP and HTTP must check switching rules */
7826 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7827 }
7828
7829 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007830 if (curproxy->tcp_req.inspect_delay ||
7831 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7832 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7833
Emeric Brun97679e72010-09-23 17:56:44 +02007834 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7835 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7836
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007837 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007838 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007839 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007840 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007841
7842 /* If the backend does requires RDP cookie persistence, we have to
7843 * enable the corresponding analyser.
7844 */
7845 if (curproxy->options2 & PR_O2_RDPC_PRST)
7846 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7847 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007848 }
7849
7850 /***********************************************************/
7851 /* At this point, target names have already been resolved. */
7852 /***********************************************************/
7853
7854 /* Check multi-process mode compatibility */
7855
7856 if (global.nbproc > 1 && global.stats_fe) {
7857 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7858 unsigned long mask;
7859
7860 mask = nbits(global.nbproc);
7861 if (global.stats_fe->bind_proc)
7862 mask &= global.stats_fe->bind_proc;
7863
7864 if (bind_conf->bind_proc)
7865 mask &= bind_conf->bind_proc;
7866
7867 /* stop here if more than one process is used */
7868 if (popcount(mask) > 1)
7869 break;
7870 }
7871 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7872 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");
7873 }
7874 }
7875
7876 /* Make each frontend inherit bind-process from its listeners when not specified. */
7877 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7878 if (curproxy->bind_proc)
7879 continue;
7880
7881 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7882 unsigned long mask;
7883
Willy Tarreaue428b082015-05-04 21:57:58 +02007884 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007885 curproxy->bind_proc |= mask;
7886 }
7887
7888 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02007889 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007890 }
7891
7892 if (global.stats_fe) {
7893 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7894 unsigned long mask;
7895
Willy Tarreaue428b082015-05-04 21:57:58 +02007896 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007897 global.stats_fe->bind_proc |= mask;
7898 }
7899 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02007900 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007901 }
7902
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007903 /* propagate bindings from frontends to backends. Don't do it if there
7904 * are any fatal errors as we must not call it with unresolved proxies.
7905 */
7906 if (!cfgerr) {
7907 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7908 if (curproxy->cap & PR_CAP_FE)
7909 propagate_processes(curproxy, NULL);
7910 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007911 }
7912
7913 /* Bind each unbound backend to all processes when not specified. */
7914 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7915 if (curproxy->bind_proc)
7916 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02007917 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007918 }
7919
7920 /*******************************************************/
7921 /* At this step, all proxies have a non-null bind_proc */
7922 /*******************************************************/
7923
7924 /* perform the final checks before creating tasks */
7925
7926 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7927 struct listener *listener;
7928 unsigned int next_id;
7929 int nbproc;
7930
7931 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007932
Emeric Brunc52962f2012-11-15 18:28:02 +01007933#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007934 /* Configure SSL for each bind line.
7935 * Note: if configuration fails at some point, the ->ctx member
7936 * remains NULL so that listeners can later detach.
7937 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007938 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007939 int alloc_ctx;
7940
Emeric Brunc52962f2012-11-15 18:28:02 +01007941 if (!bind_conf->is_ssl) {
7942 if (bind_conf->default_ctx) {
7943 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7944 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7945 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007946 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007947 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007948 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007949 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007950 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007951 cfgerr++;
7952 continue;
7953 }
7954
Emeric Brun8dc60392014-05-09 13:52:00 +02007955 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007956 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007957 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7958 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");
7959 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007960 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007961 cfgerr++;
7962 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007963 }
7964
Emeric Brunfc0421f2012-09-07 17:30:07 +02007965 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007966 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007967 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007968#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007969
Willy Tarreaue6b98942007-10-29 01:09:36 +01007970 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007971 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007972 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007973 if (!listener->luid) {
7974 /* listener ID not set, use automatic numbering with first
7975 * spare entry starting with next_luid.
7976 */
7977 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7978 listener->conf.id.key = listener->luid = next_id;
7979 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007980 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007981 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007982
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007983 /* enable separate counters */
7984 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7985 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007986 if (!listener->name)
7987 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007988 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007989
Willy Tarreaue6b98942007-10-29 01:09:36 +01007990 if (curproxy->options & PR_O_TCP_NOLING)
7991 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007992 if (!listener->maxconn)
7993 listener->maxconn = curproxy->maxconn;
7994 if (!listener->backlog)
7995 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007996 if (!listener->maxaccept)
7997 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7998
7999 /* we want to have an optimal behaviour on single process mode to
8000 * maximize the work at once, but in multi-process we want to keep
8001 * some fairness between processes, so we target half of the max
8002 * number of events to be balanced over all the processes the proxy
8003 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8004 * used to disable the limit.
8005 */
8006 if (listener->maxaccept > 0) {
8007 if (nbproc > 1)
8008 listener->maxaccept = (listener->maxaccept + 1) / 2;
8009 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8010 }
8011
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008012 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008013 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008014 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008015 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008016
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008017 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8018 listener->options |= LI_O_TCP_RULES;
8019
Willy Tarreaude3041d2010-05-31 10:56:17 +02008020 if (curproxy->mon_mask.s_addr)
8021 listener->options |= LI_O_CHK_MONNET;
8022
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008023 /* smart accept mode is automatic in HTTP mode */
8024 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008025 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008026 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8027 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008028 }
8029
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008030 /* Release unused SSL configs */
8031 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8032 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008033 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008034#ifdef USE_OPENSSL
8035 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008036 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008037 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008038 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008039 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008040 if(bind_conf->keys_ref) {
8041 free(bind_conf->keys_ref->filename);
8042 free(bind_conf->keys_ref->tlskeys);
8043 free(bind_conf->keys_ref);
8044 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008045#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008046 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008047
Willy Tarreau102df612014-05-07 23:56:38 +02008048 if (nbproc > 1) {
8049 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008050 int count, maxproc = 0;
8051
8052 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8053 count = popcount(bind_conf->bind_proc);
8054 if (count > maxproc)
8055 maxproc = count;
8056 }
8057 /* backends have 0, frontends have 1 or more */
8058 if (maxproc != 1)
8059 Warning("Proxy '%s': in multi-process mode, stats will be"
8060 " limited to process assigned to the current request.\n",
8061 curproxy->id);
8062
Willy Tarreau102df612014-05-07 23:56:38 +02008063 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8064 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8065 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008066 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008067 }
Willy Tarreau102df612014-05-07 23:56:38 +02008068 if (curproxy->appsession_name) {
8069 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
8070 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008071 }
Willy Tarreau102df612014-05-07 23:56:38 +02008072 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8073 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8074 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008075 }
8076 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008077
8078 /* create the task associated with the proxy */
8079 curproxy->task = task_new();
8080 if (curproxy->task) {
8081 curproxy->task->context = curproxy;
8082 curproxy->task->process = manage_proxy;
8083 /* no need to queue, it will be done automatically if some
8084 * listener gets limited.
8085 */
8086 curproxy->task->expire = TICK_ETERNITY;
8087 } else {
8088 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8089 curproxy->id);
8090 cfgerr++;
8091 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008092 }
8093
Willy Tarreaufbb78422011-06-05 15:38:35 +02008094 /* automatically compute fullconn if not set. We must not do it in the
8095 * loop above because cross-references are not yet fully resolved.
8096 */
8097 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8098 /* If <fullconn> is not set, let's set it to 10% of the sum of
8099 * the possible incoming frontend's maxconns.
8100 */
8101 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8102 struct proxy *fe;
8103 int total = 0;
8104
8105 /* sum up the number of maxconns of frontends which
8106 * reference this backend at least once or which are
8107 * the same one ('listen').
8108 */
8109 for (fe = proxy; fe; fe = fe->next) {
8110 struct switching_rule *rule;
8111 struct hdr_exp *exp;
8112 int found = 0;
8113
8114 if (!(fe->cap & PR_CAP_FE))
8115 continue;
8116
8117 if (fe == curproxy) /* we're on a "listen" instance */
8118 found = 1;
8119
8120 if (fe->defbe.be == curproxy) /* "default_backend" */
8121 found = 1;
8122
8123 /* check if a "use_backend" rule matches */
8124 if (!found) {
8125 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008126 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008127 found = 1;
8128 break;
8129 }
8130 }
8131 }
8132
8133 /* check if a "reqsetbe" rule matches */
8134 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
8135 if (exp->action == ACT_SETBE &&
8136 (struct proxy *)exp->replace == curproxy) {
8137 found = 1;
8138 break;
8139 }
8140 }
8141
8142 /* now we've checked all possible ways to reference a backend
8143 * from a frontend.
8144 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008145 if (!found)
8146 continue;
8147 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008148 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008149 /* we have the sum of the maxconns in <total>. We only
8150 * keep 10% of that sum to set the default fullconn, with
8151 * a hard minimum of 1 (to avoid a divide by zero).
8152 */
8153 curproxy->fullconn = (total + 9) / 10;
8154 if (!curproxy->fullconn)
8155 curproxy->fullconn = 1;
8156 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008157 }
8158
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008159 /*
8160 * Recount currently required checks.
8161 */
8162
8163 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8164 int optnum;
8165
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008166 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8167 if (curproxy->options & cfg_opts[optnum].val)
8168 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008169
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008170 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8171 if (curproxy->options2 & cfg_opts2[optnum].val)
8172 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008173 }
8174
Willy Tarreau0fca4832015-05-01 19:12:05 +02008175 /* compute the required process bindings for the peers */
8176 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8177 if (curproxy->table.peers.p)
8178 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8179
Willy Tarreau122541c2011-09-07 21:24:49 +02008180 if (peers) {
8181 struct peers *curpeers = peers, **last;
8182 struct peer *p, *pb;
8183
Willy Tarreau1e273012015-05-01 19:15:17 +02008184 /* Remove all peers sections which don't have a valid listener,
8185 * which are not used by any table, or which are bound to more
8186 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008187 */
8188 last = &peers;
8189 while (*last) {
8190 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008191
8192 if (curpeers->state == PR_STSTOPPED) {
8193 /* the "disabled" keyword was present */
8194 if (curpeers->peers_fe)
8195 stop_proxy(curpeers->peers_fe);
8196 curpeers->peers_fe = NULL;
8197 }
8198 else if (!curpeers->peers_fe) {
8199 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8200 curpeers->id, localpeer);
8201 }
Willy Tarreau1e273012015-05-01 19:15:17 +02008202 else if (popcount(curpeers->peers_fe->bind_proc) != 1) {
8203 /* either it's totally stopped or too much used */
8204 if (curpeers->peers_fe->bind_proc) {
8205 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008206 "running in different processes (%d different ones). "
8207 "Check global.nbproc and all tables' bind-process "
8208 "settings.\n", curpeers->id, popcount(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008209 cfgerr++;
8210 }
8211 stop_proxy(curpeers->peers_fe);
8212 curpeers->peers_fe = NULL;
8213 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008214 else {
Willy Tarreau122541c2011-09-07 21:24:49 +02008215 last = &curpeers->next;
8216 continue;
8217 }
8218
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008219 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008220 p = curpeers->remote;
8221 while (p) {
8222 pb = p->next;
8223 free(p->id);
8224 free(p);
8225 p = pb;
8226 }
8227
8228 /* Destroy and unlink this curpeers section.
8229 * Note: curpeers is backed up into *last.
8230 */
8231 free(curpeers->id);
8232 curpeers = curpeers->next;
8233 free(*last);
8234 *last = curpeers;
8235 }
8236 }
8237
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008238 /* initialize stick-tables on backend capable proxies. This must not
8239 * be done earlier because the data size may be discovered while parsing
8240 * other proxies.
8241 */
8242 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8243 if (curproxy->state == PR_STSTOPPED)
8244 continue;
8245
8246 if (!stktable_init(&curproxy->table)) {
8247 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8248 cfgerr++;
8249 }
8250 }
8251
Simon Horman0d16a402015-01-30 11:22:58 +09008252 if (mailers) {
8253 struct mailers *curmailers = mailers, **last;
8254 struct mailer *m, *mb;
8255
8256 /* Remove all mailers sections which don't have a valid listener.
8257 * This can happen when a mailers section is never referenced.
8258 */
8259 last = &mailers;
8260 while (*last) {
8261 curmailers = *last;
8262 if (curmailers->users) {
8263 last = &curmailers->next;
8264 continue;
8265 }
8266
8267 Warning("Removing incomplete section 'mailers %s'.\n",
8268 curmailers->id);
8269
8270 m = curmailers->mailer_list;
8271 while (m) {
8272 mb = m->next;
8273 free(m->id);
8274 free(m);
8275 m = mb;
8276 }
8277
8278 /* Destroy and unlink this curmailers section.
8279 * Note: curmailers is backed up into *last.
8280 */
8281 free(curmailers->id);
8282 curmailers = curmailers->next;
8283 free(*last);
8284 *last = curmailers;
8285 }
8286 }
8287
Willy Tarreau34eb6712011-10-24 18:15:04 +02008288 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008289 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008290 MEM_F_SHARED);
8291
Willy Tarreaubb925012009-07-23 13:36:36 +02008292 if (cfgerr > 0)
8293 err_code |= ERR_ALERT | ERR_FATAL;
8294 out:
8295 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008296}
8297
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008298/*
8299 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8300 * parsing sessions.
8301 */
8302void cfg_register_keywords(struct cfg_kw_list *kwl)
8303{
8304 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8305}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008306
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008307/*
8308 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8309 */
8310void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8311{
8312 LIST_DEL(&kwl->list);
8313 LIST_INIT(&kwl->list);
8314}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008315
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008316/* this function register new section in the haproxy configuration file.
8317 * <section_name> is the name of this new section and <section_parser>
8318 * is the called parser. If two section declaration have the same name,
8319 * only the first declared is used.
8320 */
8321int cfg_register_section(char *section_name,
8322 int (*section_parser)(const char *, int, char **, int))
8323{
8324 struct cfg_section *cs;
8325
8326 cs = calloc(1, sizeof(*cs));
8327 if (!cs) {
8328 Alert("register section '%s': out of memory.\n", section_name);
8329 return 0;
8330 }
8331
8332 cs->section_name = section_name;
8333 cs->section_parser = section_parser;
8334
8335 LIST_ADDQ(&sections, &cs->list);
8336
8337 return 1;
8338}
8339
Willy Tarreaubaaee002006-06-26 02:48:02 +02008340/*
8341 * Local variables:
8342 * c-indent-level: 8
8343 * c-basic-offset: 8
8344 * End:
8345 */