blob: edaee56a02e5602d069bec5ede1311bc0c73ebb1 [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 Tarreau9420b122013-12-15 18:58:25 +0100157 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100158 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
159 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
160 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
161 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
162 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100163#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100164 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100165#else
166 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100167#endif
168
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100169 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100170};
171
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100172/* proxy->options2 */
173static const struct cfg_opt cfg_opts2[] =
174{
175#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100176 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
177 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
178 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100179#else
180 { "splice-request", 0, 0, 0, 0 },
181 { "splice-response", 0, 0, 0, 0 },
182 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100183#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100184 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
185 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
186 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
187 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
188 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
189 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
190 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
191 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
192 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400193 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100194 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200195 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200196 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100197 { NULL, 0, 0, 0 }
198};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199
Willy Tarreau6daf3432008-01-22 16:44:08 +0100200static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
202int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100203int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200205/* List head of all known configuration keywords */
206static struct cfg_kw_list cfg_keywords = {
207 .list = LIST_HEAD_INIT(cfg_keywords.list)
208};
209
Willy Tarreaubaaee002006-06-26 02:48:02 +0200210/*
211 * converts <str> to a list of listeners which are dynamically allocated.
212 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
213 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
214 * - <port> is a numerical port from 1 to 65535 ;
215 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
216 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200217 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
218 * not NULL, it must be a valid pointer to either NULL or a freeable area that
219 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200221int 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 +0200222{
223 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100224 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 int port, end;
226
227 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200228
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100230 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100231 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200232
233 str = next;
234 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100235 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236 *next++ = 0;
237 }
238
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100239 ss2 = str2sa_range(str, &port, &end, err,
240 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
241 if (!ss2)
242 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100244 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100245 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200246 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100247 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100250 if (!port || !end) {
251 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
252 goto fail;
253 }
254
Emeric Bruned760922010-10-22 17:59:25 +0200255 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200256 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200257 goto fail;
258 }
259
260 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200261 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200262 goto fail;
263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200264 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100265 else if (ss2->ss_family == AF_UNSPEC) {
266 socklen_t addr_len;
267
268 /* We want to attach to an already bound fd whose number
269 * is in the addr part of ss2 when cast to sockaddr_in.
270 * Note that by definition there is a single listener.
271 * We still have to determine the address family to
272 * register the correct protocol.
273 */
274 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
275 addr_len = sizeof(*ss2);
276 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
277 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
278 goto fail;
279 }
280
281 port = end = get_host_port(ss2);
282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200283
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100284 /* OK the address looks correct */
285 ss = *ss2;
286
Willy Tarreaubaaee002006-06-26 02:48:02 +0200287 for (; port <= end; port++) {
288 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100289 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200290 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
291 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
292 l->frontend = curproxy;
293 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294
Willy Tarreau40aa0702013-03-10 23:51:38 +0100295 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200297 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100298 l->state = LI_INIT;
299
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100300 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100302 tcpv4_add_listener(l);
303 }
Emeric Bruned760922010-10-22 17:59:25 +0200304 else if (ss.ss_family == AF_INET6) {
305 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
306 tcpv6_add_listener(l);
307 }
308 else {
Emeric Bruned760922010-10-22 17:59:25 +0200309 uxst_add_listener(l);
310 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200311
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200312 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100313 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200314 } /* end for(port) */
315 } /* end while(next) */
316 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200317 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318 fail:
319 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200320 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200321}
322
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200323/* Report a warning if a rule is placed after a 'tcp-request content' rule.
324 * Return 1 if the warning has been emitted, otherwise 0.
325 */
326int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
327{
328 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
329 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
330 file, line, arg);
331 return 1;
332 }
333 return 0;
334}
335
Willy Tarreau61d18892009-03-31 10:49:21 +0200336/* Report a warning if a rule is placed after a 'block' rule.
337 * Return 1 if the warning has been emitted, otherwise 0.
338 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100339int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200340{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200341 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200342 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
343 file, line, arg);
344 return 1;
345 }
346 return 0;
347}
348
Willy Tarreau5002f572014-04-23 01:32:02 +0200349/* Report a warning if a rule is placed after an 'http_request' rule.
350 * Return 1 if the warning has been emitted, otherwise 0.
351 */
352int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
353{
354 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
355 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
356 file, line, arg);
357 return 1;
358 }
359 return 0;
360}
361
Willy Tarreau61d18892009-03-31 10:49:21 +0200362/* Report a warning if a rule is placed after a reqrewrite rule.
363 * Return 1 if the warning has been emitted, otherwise 0.
364 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100365int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200366{
367 if (proxy->req_exp) {
368 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
369 file, line, arg);
370 return 1;
371 }
372 return 0;
373}
374
375/* Report a warning if a rule is placed after a reqadd rule.
376 * Return 1 if the warning has been emitted, otherwise 0.
377 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100378int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200379{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100380 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200381 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
382 file, line, arg);
383 return 1;
384 }
385 return 0;
386}
387
388/* Report a warning if a rule is placed after a redirect rule.
389 * Return 1 if the warning has been emitted, otherwise 0.
390 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100391int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200392{
393 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
394 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
395 file, line, arg);
396 return 1;
397 }
398 return 0;
399}
400
401/* Report a warning if a rule is placed after a 'use_backend' rule.
402 * Return 1 if the warning has been emitted, otherwise 0.
403 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100404int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200405{
406 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
407 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
408 file, line, arg);
409 return 1;
410 }
411 return 0;
412}
413
Willy Tarreauee445d92014-04-23 01:39:04 +0200414/* Report a warning if a rule is placed after a 'use-server' rule.
415 * Return 1 if the warning has been emitted, otherwise 0.
416 */
417int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
418{
419 if (!LIST_ISEMPTY(&proxy->server_rules)) {
420 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
421 file, line, arg);
422 return 1;
423 }
424 return 0;
425}
426
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200427/* report a warning if a "tcp request connection" rule is dangerously placed */
428int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
429{
430 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
431 warnif_rule_after_block(proxy, file, line, arg) ||
432 warnif_rule_after_http_req(proxy, file, line, arg) ||
433 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
434 warnif_rule_after_reqadd(proxy, file, line, arg) ||
435 warnif_rule_after_redirect(proxy, file, line, arg) ||
436 warnif_rule_after_use_backend(proxy, file, line, arg) ||
437 warnif_rule_after_use_server(proxy, file, line, arg);
438}
439
440/* report a warning if a "tcp request content" rule is dangerously placed */
441int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
442{
443 return warnif_rule_after_block(proxy, file, line, arg) ||
444 warnif_rule_after_http_req(proxy, file, line, arg) ||
445 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
446 warnif_rule_after_reqadd(proxy, file, line, arg) ||
447 warnif_rule_after_redirect(proxy, file, line, arg) ||
448 warnif_rule_after_use_backend(proxy, file, line, arg) ||
449 warnif_rule_after_use_server(proxy, file, line, arg);
450}
451
Willy Tarreau61d18892009-03-31 10:49:21 +0200452/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100453int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200454{
Willy Tarreau5002f572014-04-23 01:32:02 +0200455 return warnif_rule_after_http_req(proxy, file, line, arg) ||
456 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
457 warnif_rule_after_reqadd(proxy, file, line, arg) ||
458 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200459 warnif_rule_after_use_backend(proxy, file, line, arg) ||
460 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200461}
462
463/* report a warning if an http-request rule is dangerously placed */
464int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
465{
Willy Tarreau61d18892009-03-31 10:49:21 +0200466 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
467 warnif_rule_after_reqadd(proxy, file, line, arg) ||
468 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200469 warnif_rule_after_use_backend(proxy, file, line, arg) ||
470 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200471}
472
473/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100474int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200475{
476 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
477 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200478 warnif_rule_after_use_backend(proxy, file, line, arg) ||
479 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200480}
481
482/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100483int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200484{
485 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200486 warnif_rule_after_use_backend(proxy, file, line, arg) ||
487 warnif_rule_after_use_server(proxy, file, line, arg);
488}
489
490/* report a warning if a redirect rule is dangerously placed */
491int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
492{
493 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
494 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200495}
496
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100497/* Report it if a request ACL condition uses some keywords that are incompatible
498 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
499 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
500 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100501 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100502static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100503{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100504 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200505 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100506
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100507 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100508 return 0;
509
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100510 acl = acl_cond_conflicts(cond, where);
511 if (acl) {
512 if (acl->name && *acl->name)
513 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
514 file, line, acl->name, sample_ckp_names(where));
515 else
516 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 +0200517 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100518 return ERR_WARN;
519 }
520 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100521 return 0;
522
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100523 if (acl->name && *acl->name)
524 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200525 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100526 else
527 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200528 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100529 return ERR_WARN;
530}
531
Willy Tarreaubaaee002006-06-26 02:48:02 +0200532/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 * parse a line in a <global> section. Returns the error code, 0 if OK, or
534 * any combination of :
535 * - ERR_ABORT: must abort ASAP
536 * - ERR_FATAL: we can continue parsing but not start the service
537 * - ERR_WARN: a warning has been emitted
538 * - ERR_ALERT: an alert has been emitted
539 * Only the two first ones can stop processing, the two others are just
540 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200541 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200542int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200543{
Willy Tarreau058e9072009-07-20 09:30:05 +0200544 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200545 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200546
547 if (!strcmp(args[0], "global")) { /* new section */
548 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200549 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200550 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200551 else if (!strcmp(args[0], "ca-base")) {
552#ifdef USE_OPENSSL
553 if (global.ca_base != NULL) {
554 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
555 err_code |= ERR_ALERT;
556 goto out;
557 }
558 if (*(args[1]) == 0) {
559 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
560 err_code |= ERR_ALERT | ERR_FATAL;
561 goto out;
562 }
563 global.ca_base = strdup(args[1]);
564#else
565 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
566 err_code |= ERR_ALERT | ERR_FATAL;
567 goto out;
568#endif
569 }
570 else if (!strcmp(args[0], "crt-base")) {
571#ifdef USE_OPENSSL
572 if (global.crt_base != NULL) {
573 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
574 err_code |= ERR_ALERT;
575 goto out;
576 }
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582 global.crt_base = strdup(args[1]);
583#else
584 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
585 err_code |= ERR_ALERT | ERR_FATAL;
586 goto out;
587#endif
588 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 else if (!strcmp(args[0], "daemon")) {
590 global.mode |= MODE_DAEMON;
591 }
592 else if (!strcmp(args[0], "debug")) {
593 global.mode |= MODE_DEBUG;
594 }
595 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100596 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200597 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200598 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100599 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200600 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100602 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200603 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100604 else if (!strcmp(args[0], "nosplice")) {
605 global.tune.options &= ~GTUNE_USE_SPLICE;
606 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200607 else if (!strcmp(args[0], "nogetaddrinfo")) {
608 global.tune.options &= ~GTUNE_USE_GAI;
609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610 else if (!strcmp(args[0], "quiet")) {
611 global.mode |= MODE_QUIET;
612 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200613 else if (!strcmp(args[0], "tune.maxpollevents")) {
614 if (global.tune.maxpollevents != 0) {
615 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200616 err_code |= ERR_ALERT;
617 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200618 }
619 if (*(args[1]) == 0) {
620 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT | ERR_FATAL;
622 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200623 }
624 global.tune.maxpollevents = atol(args[1]);
625 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100626 else if (!strcmp(args[0], "tune.maxaccept")) {
627 if (global.tune.maxaccept != 0) {
628 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200629 err_code |= ERR_ALERT;
630 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100631 }
632 if (*(args[1]) == 0) {
633 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200634 err_code |= ERR_ALERT | ERR_FATAL;
635 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100636 }
637 global.tune.maxaccept = atol(args[1]);
638 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200639 else if (!strcmp(args[0], "tune.chksize")) {
640 if (*(args[1]) == 0) {
641 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
642 err_code |= ERR_ALERT | ERR_FATAL;
643 goto out;
644 }
645 global.tune.chksize = atol(args[1]);
646 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200647#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200648 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
649 global.tune.sslprivatecache = 1;
650 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100651 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200652 if (*(args[1]) == 0) {
653 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
654 err_code |= ERR_ALERT | ERR_FATAL;
655 goto out;
656 }
657 global.tune.sslcachesize = atol(args[1]);
658 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100659 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
660 unsigned int ssllifetime;
661 const char *res;
662
663 if (*(args[1]) == 0) {
664 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
665 err_code |= ERR_ALERT | ERR_FATAL;
666 goto out;
667 }
668
669 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
670 if (res) {
671 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
672 file, linenum, *res, args[0]);
673 err_code |= ERR_ALERT | ERR_FATAL;
674 goto out;
675 }
676
677 global.tune.ssllifetime = ssllifetime;
678 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100679 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
680 if (*(args[1]) == 0) {
681 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
682 err_code |= ERR_ALERT | ERR_FATAL;
683 goto out;
684 }
685 global.tune.ssl_max_record = atol(args[1]);
686 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200687 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
688 if (*(args[1]) == 0) {
689 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
690 err_code |= ERR_ALERT | ERR_FATAL;
691 goto out;
692 }
693 global.tune.ssl_default_dh_param = atol(args[1]);
694 if (global.tune.ssl_default_dh_param < 1024) {
695 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
696 err_code |= ERR_ALERT | ERR_FATAL;
697 goto out;
698 }
699 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200700#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100701 else if (!strcmp(args[0], "tune.buffers.limit")) {
702 if (*(args[1]) == 0) {
703 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
704 err_code |= ERR_ALERT | ERR_FATAL;
705 goto out;
706 }
707 global.tune.buf_limit = atol(args[1]);
708 if (global.tune.buf_limit) {
709 if (global.tune.buf_limit < 3)
710 global.tune.buf_limit = 3;
711 if (global.tune.buf_limit <= global.tune.reserved_bufs)
712 global.tune.buf_limit = global.tune.reserved_bufs + 1;
713 }
714 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100715 else if (!strcmp(args[0], "tune.buffers.reserve")) {
716 if (*(args[1]) == 0) {
717 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
718 err_code |= ERR_ALERT | ERR_FATAL;
719 goto out;
720 }
721 global.tune.reserved_bufs = atol(args[1]);
722 if (global.tune.reserved_bufs < 2)
723 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100724 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
725 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100726 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200727 else if (!strcmp(args[0], "tune.bufsize")) {
728 if (*(args[1]) == 0) {
729 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
730 err_code |= ERR_ALERT | ERR_FATAL;
731 goto out;
732 }
733 global.tune.bufsize = atol(args[1]);
734 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
735 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100736 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100737 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200738 }
739 else if (!strcmp(args[0], "tune.maxrewrite")) {
740 if (*(args[1]) == 0) {
741 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
742 err_code |= ERR_ALERT | ERR_FATAL;
743 goto out;
744 }
745 global.tune.maxrewrite = atol(args[1]);
746 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
747 global.tune.maxrewrite = global.tune.bufsize / 2;
748 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100749 else if (!strcmp(args[0], "tune.idletimer")) {
750 unsigned int idle;
751 const char *res;
752
753 if (*(args[1]) == 0) {
754 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
757 }
758
759 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
760 if (res) {
761 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
762 file, linenum, *res, args[0]);
763 err_code |= ERR_ALERT | ERR_FATAL;
764 goto out;
765 }
766
767 if (idle > 65535) {
768 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
769 err_code |= ERR_ALERT | ERR_FATAL;
770 goto out;
771 }
772 global.tune.idle_timer = idle;
773 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100774 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
775 if (global.tune.client_rcvbuf != 0) {
776 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
777 err_code |= ERR_ALERT;
778 goto out;
779 }
780 if (*(args[1]) == 0) {
781 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
782 err_code |= ERR_ALERT | ERR_FATAL;
783 goto out;
784 }
785 global.tune.client_rcvbuf = atol(args[1]);
786 }
787 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
788 if (global.tune.server_rcvbuf != 0) {
789 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
790 err_code |= ERR_ALERT;
791 goto out;
792 }
793 if (*(args[1]) == 0) {
794 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
795 err_code |= ERR_ALERT | ERR_FATAL;
796 goto out;
797 }
798 global.tune.server_rcvbuf = atol(args[1]);
799 }
800 else if (!strcmp(args[0], "tune.sndbuf.client")) {
801 if (global.tune.client_sndbuf != 0) {
802 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
803 err_code |= ERR_ALERT;
804 goto out;
805 }
806 if (*(args[1]) == 0) {
807 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
808 err_code |= ERR_ALERT | ERR_FATAL;
809 goto out;
810 }
811 global.tune.client_sndbuf = atol(args[1]);
812 }
813 else if (!strcmp(args[0], "tune.sndbuf.server")) {
814 if (global.tune.server_sndbuf != 0) {
815 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
816 err_code |= ERR_ALERT;
817 goto out;
818 }
819 if (*(args[1]) == 0) {
820 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
821 err_code |= ERR_ALERT | ERR_FATAL;
822 goto out;
823 }
824 global.tune.server_sndbuf = atol(args[1]);
825 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200826 else if (!strcmp(args[0], "tune.pipesize")) {
827 if (*(args[1]) == 0) {
828 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
829 err_code |= ERR_ALERT | ERR_FATAL;
830 goto out;
831 }
832 global.tune.pipesize = atol(args[1]);
833 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100834 else if (!strcmp(args[0], "tune.http.cookielen")) {
835 if (*(args[1]) == 0) {
836 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
837 err_code |= ERR_ALERT | ERR_FATAL;
838 goto out;
839 }
840 global.tune.cookie_len = atol(args[1]) + 1;
841 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200842 else if (!strcmp(args[0], "tune.http.maxhdr")) {
843 if (*(args[1]) == 0) {
844 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
845 err_code |= ERR_ALERT | ERR_FATAL;
846 goto out;
847 }
848 global.tune.max_http_hdr = atol(args[1]);
849 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100850 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
851#ifdef USE_ZLIB
852 if (*args[1]) {
853 global.tune.zlibmemlevel = atoi(args[1]);
854 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
855 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
856 file, linenum, args[0]);
857 err_code |= ERR_ALERT | ERR_FATAL;
858 goto out;
859 }
860 } else {
861 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
862 file, linenum, args[0]);
863 err_code |= ERR_ALERT | ERR_FATAL;
864 goto out;
865 }
866#else
867 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
868 err_code |= ERR_ALERT | ERR_FATAL;
869 goto out;
870#endif
871 }
872 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
873#ifdef USE_ZLIB
874 if (*args[1]) {
875 global.tune.zlibwindowsize = atoi(args[1]);
876 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
877 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
878 file, linenum, args[0]);
879 err_code |= ERR_ALERT | ERR_FATAL;
880 goto out;
881 }
882 } else {
883 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
884 file, linenum, args[0]);
885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
887 }
888#else
889 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
892#endif
893 }
William Lallemandf3747832012-11-09 12:33:10 +0100894 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
895 if (*args[1]) {
896 global.tune.comp_maxlevel = atoi(args[1]);
897 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
898 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
899 file, linenum, args[0]);
900 err_code |= ERR_ALERT | ERR_FATAL;
901 goto out;
902 }
903 } else {
904 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
905 file, linenum, args[0]);
906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
909 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910 else if (!strcmp(args[0], "uid")) {
911 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200912 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200913 err_code |= ERR_ALERT;
914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200915 }
916 if (*(args[1]) == 0) {
917 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200918 err_code |= ERR_ALERT | ERR_FATAL;
919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920 }
921 global.uid = atol(args[1]);
922 }
923 else if (!strcmp(args[0], "gid")) {
924 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200925 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200926 err_code |= ERR_ALERT;
927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200928 }
929 if (*(args[1]) == 0) {
930 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200931 err_code |= ERR_ALERT | ERR_FATAL;
932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 }
934 global.gid = atol(args[1]);
935 }
Simon Horman98637e52014-06-20 12:30:16 +0900936 else if (!strcmp(args[0], "external-check")) {
937 global.external_check = 1;
938 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200939 /* user/group name handling */
940 else if (!strcmp(args[0], "user")) {
941 struct passwd *ha_user;
942 if (global.uid != 0) {
943 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200944 err_code |= ERR_ALERT;
945 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200946 }
947 errno = 0;
948 ha_user = getpwnam(args[1]);
949 if (ha_user != NULL) {
950 global.uid = (int)ha_user->pw_uid;
951 }
952 else {
953 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 +0200954 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200955 }
956 }
957 else if (!strcmp(args[0], "group")) {
958 struct group *ha_group;
959 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200960 Alert("parsing [%s:%d] : gid/group was 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_group = getgrnam(args[1]);
966 if (ha_group != NULL) {
967 global.gid = (int)ha_group->gr_gid;
968 }
969 else {
970 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 +0200971 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200972 }
973 }
974 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200975 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200976 if (*(args[1]) == 0) {
977 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200978 err_code |= ERR_ALERT | ERR_FATAL;
979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980 }
981 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100982 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
983 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
984 file, linenum, args[0], LONGBITS, global.nbproc);
985 err_code |= ERR_ALERT | ERR_FATAL;
986 goto out;
987 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200988 }
989 else if (!strcmp(args[0], "maxconn")) {
990 if (global.maxconn != 0) {
991 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200992 err_code |= ERR_ALERT;
993 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200994 }
995 if (*(args[1]) == 0) {
996 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200997 err_code |= ERR_ALERT | ERR_FATAL;
998 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200999 }
1000 global.maxconn = atol(args[1]);
1001#ifdef SYSTEM_MAXCONN
1002 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1003 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);
1004 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001005 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001006 }
1007#endif /* SYSTEM_MAXCONN */
1008 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001009 else if (!strcmp(args[0], "maxsslconn")) {
1010#ifdef USE_OPENSSL
1011 if (*(args[1]) == 0) {
1012 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1013 err_code |= ERR_ALERT | ERR_FATAL;
1014 goto out;
1015 }
1016 global.maxsslconn = atol(args[1]);
1017#else
Emeric Brun0914df82012-10-02 18:45:42 +02001018 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1019 err_code |= ERR_ALERT | ERR_FATAL;
1020 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001021#endif
1022 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001023 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1024#ifdef USE_OPENSSL
1025 if (*(args[1]) == 0) {
1026 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1027 err_code |= ERR_ALERT | ERR_FATAL;
1028 goto out;
1029 }
1030 free(global.listen_default_ciphers);
1031 global.listen_default_ciphers = strdup(args[1]);
1032#else
1033 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1034 err_code |= ERR_ALERT | ERR_FATAL;
1035 goto out;
1036#endif
1037 }
1038 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1039#ifdef USE_OPENSSL
1040 if (*(args[1]) == 0) {
1041 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1042 err_code |= ERR_ALERT | ERR_FATAL;
1043 goto out;
1044 }
1045 free(global.connect_default_ciphers);
1046 global.connect_default_ciphers = strdup(args[1]);
1047#else
1048 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1049 err_code |= ERR_ALERT | ERR_FATAL;
1050 goto out;
1051#endif
1052 }
Emeric Brun850efd52014-01-29 12:24:34 +01001053 else if (!strcmp(args[0], "ssl-server-verify")) {
1054 if (*(args[1]) == 0) {
1055 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1056 err_code |= ERR_ALERT | ERR_FATAL;
1057 goto out;
1058 }
1059 if (strcmp(args[1],"none") == 0)
1060 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1061 else if (strcmp(args[1],"required") == 0)
1062 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1063 else {
1064 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1065 err_code |= ERR_ALERT | ERR_FATAL;
1066 goto out;
1067 }
1068 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001069 else if (!strcmp(args[0], "maxconnrate")) {
1070 if (global.cps_lim != 0) {
1071 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1072 err_code |= ERR_ALERT;
1073 goto out;
1074 }
1075 if (*(args[1]) == 0) {
1076 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1077 err_code |= ERR_ALERT | ERR_FATAL;
1078 goto out;
1079 }
1080 global.cps_lim = atol(args[1]);
1081 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001082 else if (!strcmp(args[0], "maxsessrate")) {
1083 if (global.sps_lim != 0) {
1084 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1085 err_code |= ERR_ALERT;
1086 goto out;
1087 }
1088 if (*(args[1]) == 0) {
1089 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1090 err_code |= ERR_ALERT | ERR_FATAL;
1091 goto out;
1092 }
1093 global.sps_lim = atol(args[1]);
1094 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001095 else if (!strcmp(args[0], "maxsslrate")) {
1096 if (global.ssl_lim != 0) {
1097 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1098 err_code |= ERR_ALERT;
1099 goto out;
1100 }
1101 if (*(args[1]) == 0) {
1102 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1103 err_code |= ERR_ALERT | ERR_FATAL;
1104 goto out;
1105 }
1106 global.ssl_lim = atol(args[1]);
1107 }
William Lallemandd85f9172012-11-09 17:05:39 +01001108 else if (!strcmp(args[0], "maxcomprate")) {
1109 if (*(args[1]) == 0) {
1110 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1111 err_code |= ERR_ALERT | ERR_FATAL;
1112 goto out;
1113 }
1114 global.comp_rate_lim = atoi(args[1]) * 1024;
1115 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001116 else if (!strcmp(args[0], "maxpipes")) {
1117 if (global.maxpipes != 0) {
1118 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001119 err_code |= ERR_ALERT;
1120 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001121 }
1122 if (*(args[1]) == 0) {
1123 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001124 err_code |= ERR_ALERT | ERR_FATAL;
1125 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001126 }
1127 global.maxpipes = atol(args[1]);
1128 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001129 else if (!strcmp(args[0], "maxzlibmem")) {
1130 if (*(args[1]) == 0) {
1131 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1132 err_code |= ERR_ALERT | ERR_FATAL;
1133 goto out;
1134 }
William Lallemande3a7d992012-11-20 11:25:20 +01001135 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001136 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001137 else if (!strcmp(args[0], "maxcompcpuusage")) {
1138 if (*(args[1]) == 0) {
1139 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1140 err_code |= ERR_ALERT | ERR_FATAL;
1141 goto out;
1142 }
1143 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001144 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001145 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1146 err_code |= ERR_ALERT | ERR_FATAL;
1147 goto out;
1148 }
1149}
1150
Willy Tarreaubaaee002006-06-26 02:48:02 +02001151 else if (!strcmp(args[0], "ulimit-n")) {
1152 if (global.rlimit_nofile != 0) {
1153 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001154 err_code |= ERR_ALERT;
1155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 }
1157 if (*(args[1]) == 0) {
1158 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001159 err_code |= ERR_ALERT | ERR_FATAL;
1160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001161 }
1162 global.rlimit_nofile = atol(args[1]);
1163 }
1164 else if (!strcmp(args[0], "chroot")) {
1165 if (global.chroot != NULL) {
1166 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001167 err_code |= ERR_ALERT;
1168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001169 }
1170 if (*(args[1]) == 0) {
1171 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001172 err_code |= ERR_ALERT | ERR_FATAL;
1173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001174 }
1175 global.chroot = strdup(args[1]);
1176 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001177 else if (!strcmp(args[0], "description")) {
1178 int i, len=0;
1179 char *d;
1180
1181 if (!*args[1]) {
1182 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1183 file, linenum, args[0]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 goto out;
1186 }
1187
Willy Tarreau348acfe2014-04-14 15:00:39 +02001188 for (i = 1; *args[i]; i++)
1189 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001190
1191 if (global.desc)
1192 free(global.desc);
1193
1194 global.desc = d = (char *)calloc(1, len);
1195
Willy Tarreau348acfe2014-04-14 15:00:39 +02001196 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1197 for (i = 2; *args[i]; i++)
1198 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001199 }
1200 else if (!strcmp(args[0], "node")) {
1201 int i;
1202 char c;
1203
1204 for (i=0; args[1][i]; i++) {
1205 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001206 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1207 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001208 break;
1209 }
1210
1211 if (!i || args[1][i]) {
1212 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1213 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1214 file, linenum, args[0]);
1215 err_code |= ERR_ALERT | ERR_FATAL;
1216 goto out;
1217 }
1218
1219 if (global.node)
1220 free(global.node);
1221
1222 global.node = strdup(args[1]);
1223 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001224 else if (!strcmp(args[0], "pidfile")) {
1225 if (global.pidfile != NULL) {
1226 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001227 err_code |= ERR_ALERT;
1228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001229 }
1230 if (*(args[1]) == 0) {
1231 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001232 err_code |= ERR_ALERT | ERR_FATAL;
1233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001234 }
1235 global.pidfile = strdup(args[1]);
1236 }
Emeric Bruned760922010-10-22 17:59:25 +02001237 else if (!strcmp(args[0], "unix-bind")) {
1238 int cur_arg = 1;
1239 while (*(args[cur_arg])) {
1240 if (!strcmp(args[cur_arg], "prefix")) {
1241 if (global.unix_bind.prefix != NULL) {
1242 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1243 err_code |= ERR_ALERT;
1244 cur_arg += 2;
1245 continue;
1246 }
1247
1248 if (*(args[cur_arg+1]) == 0) {
1249 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1250 err_code |= ERR_ALERT | ERR_FATAL;
1251 goto out;
1252 }
1253 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1254 cur_arg += 2;
1255 continue;
1256 }
1257
1258 if (!strcmp(args[cur_arg], "mode")) {
1259
1260 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1261 cur_arg += 2;
1262 continue;
1263 }
1264
1265 if (!strcmp(args[cur_arg], "uid")) {
1266
1267 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1268 cur_arg += 2;
1269 continue;
1270 }
1271
1272 if (!strcmp(args[cur_arg], "gid")) {
1273
1274 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1275 cur_arg += 2;
1276 continue;
1277 }
1278
1279 if (!strcmp(args[cur_arg], "user")) {
1280 struct passwd *user;
1281
1282 user = getpwnam(args[cur_arg + 1]);
1283 if (!user) {
1284 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1285 file, linenum, args[0], args[cur_arg + 1 ]);
1286 err_code |= ERR_ALERT | ERR_FATAL;
1287 goto out;
1288 }
1289
1290 global.unix_bind.ux.uid = user->pw_uid;
1291 cur_arg += 2;
1292 continue;
1293 }
1294
1295 if (!strcmp(args[cur_arg], "group")) {
1296 struct group *group;
1297
1298 group = getgrnam(args[cur_arg + 1]);
1299 if (!group) {
1300 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1301 file, linenum, args[0], args[cur_arg + 1 ]);
1302 err_code |= ERR_ALERT | ERR_FATAL;
1303 goto out;
1304 }
1305
1306 global.unix_bind.ux.gid = group->gr_gid;
1307 cur_arg += 2;
1308 continue;
1309 }
1310
Willy Tarreaub48f9582011-09-05 01:17:06 +02001311 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001312 file, linenum, args[0]);
1313 err_code |= ERR_ALERT | ERR_FATAL;
1314 goto out;
1315 }
1316 }
William Lallemand0f99e342011-10-12 17:50:54 +02001317 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1318 /* delete previous herited or defined syslog servers */
1319 struct logsrv *back;
1320 struct logsrv *tmp;
1321
1322 if (*(args[1]) != 0) {
1323 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1324 err_code |= ERR_ALERT | ERR_FATAL;
1325 goto out;
1326 }
1327
1328 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1329 LIST_DEL(&tmp->list);
1330 free(tmp);
1331 }
1332 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001333 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001334 struct sockaddr_storage *sk;
1335 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001336 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001337 int arg = 0;
1338 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001339
Willy Tarreaubaaee002006-06-26 02:48:02 +02001340 if (*(args[1]) == 0 || *(args[2]) == 0) {
1341 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001342 err_code |= ERR_ALERT | ERR_FATAL;
1343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001344 }
William Lallemand0f99e342011-10-12 17:50:54 +02001345
1346 logsrv = calloc(1, sizeof(struct logsrv));
1347
Willy Tarreau18324f52014-06-27 18:10:07 +02001348 /* just after the address, a length may be specified */
1349 if (strcmp(args[arg+2], "len") == 0) {
1350 len = atoi(args[arg+3]);
1351 if (len < 80 || len > 65535) {
1352 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1353 file, linenum, args[arg+3]);
1354 err_code |= ERR_ALERT | ERR_FATAL;
1355 goto out;
1356 }
1357 logsrv->maxlen = len;
1358
1359 /* skip these two args */
1360 arg += 2;
1361 }
1362 else
1363 logsrv->maxlen = MAX_SYSLOG_LEN;
1364
1365 if (logsrv->maxlen > global.max_syslog_len) {
1366 global.max_syslog_len = logsrv->maxlen;
1367 logline = realloc(logline, global.max_syslog_len + 1);
1368 }
1369
1370 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001371 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001372 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001373 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001374 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001375 }
1376
William Lallemand0f99e342011-10-12 17:50:54 +02001377 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001378 if (*(args[arg+3])) {
1379 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001380 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001381 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001382 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001383 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 }
1385 }
1386
William Lallemand0f99e342011-10-12 17:50:54 +02001387 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001388 if (*(args[arg+4])) {
1389 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001390 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001391 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001392 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001393 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001394 }
1395 }
1396
Willy Tarreau902636f2013-03-10 19:44:48 +01001397 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001398 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001399 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001400 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001401 free(logsrv);
1402 goto out;
1403 }
1404 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001405
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001406 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001407 if (port1 != port2) {
1408 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1409 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001410 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001411 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001412 goto out;
1413 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001414
William Lallemand0f99e342011-10-12 17:50:54 +02001415 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001416 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001417 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001418 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001419
William Lallemand0f99e342011-10-12 17:50:54 +02001420 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001421 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001422 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1423 char *name;
1424 int len;
1425
1426 if (global.log_send_hostname != NULL) {
1427 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1428 err_code |= ERR_ALERT;
1429 goto out;
1430 }
1431
1432 if (*(args[1]))
1433 name = args[1];
1434 else
1435 name = hostname;
1436
1437 len = strlen(name);
1438
1439 /* We'll add a space after the name to respect the log format */
1440 free(global.log_send_hostname);
1441 global.log_send_hostname = malloc(len + 2);
1442 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1443 }
Kevinm48936af2010-12-22 16:08:21 +00001444 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1445 if (*(args[1]) == 0) {
1446 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1447 err_code |= ERR_ALERT | ERR_FATAL;
1448 goto out;
1449 }
1450 free(global.log_tag);
1451 global.log_tag = strdup(args[1]);
1452 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001453 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1454 if (global.spread_checks != 0) {
1455 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001456 err_code |= ERR_ALERT;
1457 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001458 }
1459 if (*(args[1]) == 0) {
1460 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001461 err_code |= ERR_ALERT | ERR_FATAL;
1462 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001463 }
1464 global.spread_checks = atol(args[1]);
1465 if (global.spread_checks < 0 || global.spread_checks > 50) {
1466 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001467 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001468 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001469 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001470 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1471 const char *err;
1472 unsigned int val;
1473
1474
1475 if (*(args[1]) == 0) {
1476 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1477 err_code |= ERR_ALERT | ERR_FATAL;
1478 goto out;
1479 }
1480
1481 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1482 if (err) {
1483 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1484 err_code |= ERR_ALERT | ERR_FATAL;
1485 }
1486 global.max_spread_checks = val;
1487 if (global.max_spread_checks < 0) {
1488 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1489 err_code |= ERR_ALERT | ERR_FATAL;
1490 }
1491 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001492 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1493#ifdef USE_CPU_AFFINITY
1494 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001495 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001496 unsigned long cpus = 0;
1497
1498 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001499 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001500 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001501 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001502 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001503 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001504 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001505 proc = atol(args[1]);
1506 if (proc >= 1 && proc <= LONGBITS)
1507 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001508 }
1509
1510 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001511 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",
1512 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001513 err_code |= ERR_ALERT | ERR_FATAL;
1514 goto out;
1515 }
1516
1517 cur_arg = 2;
1518 while (*args[cur_arg]) {
1519 unsigned int low, high;
1520
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001521 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001522 char *dash = strchr(args[cur_arg], '-');
1523
1524 low = high = str2uic(args[cur_arg]);
1525 if (dash)
1526 high = str2uic(dash + 1);
1527
1528 if (high < low) {
1529 unsigned int swap = low;
1530 low = high;
1531 high = swap;
1532 }
1533
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001534 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001535 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001536 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001537 err_code |= ERR_ALERT | ERR_FATAL;
1538 goto out;
1539 }
1540
1541 while (low <= high)
1542 cpus |= 1UL << low++;
1543 }
1544 else {
1545 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1546 file, linenum, args[0], args[cur_arg]);
1547 err_code |= ERR_ALERT | ERR_FATAL;
1548 goto out;
1549 }
1550 cur_arg++;
1551 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001552 for (i = 0; i < LONGBITS; i++)
1553 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001554 global.cpu_map[i] = cpus;
1555#else
1556 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1557 err_code |= ERR_ALERT | ERR_FATAL;
1558 goto out;
1559#endif
1560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001562 struct cfg_kw_list *kwl;
1563 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001564 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001565
1566 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1567 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1568 if (kwl->kw[index].section != CFG_GLOBAL)
1569 continue;
1570 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001571 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001572 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001573 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001574 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001575 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001576 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001577 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001578 err_code |= ERR_WARN;
1579 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001580 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001581 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001582 }
1583 }
1584 }
1585
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001587 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001589
Willy Tarreau058e9072009-07-20 09:30:05 +02001590 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001591 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001592 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001593}
1594
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001595void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001597 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598 defproxy.mode = PR_MODE_TCP;
1599 defproxy.state = PR_STNEW;
1600 defproxy.maxconn = cfg_maxpconn;
1601 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001602
Simon Horman66183002013-02-23 10:16:43 +09001603 defproxy.defsrv.check.inter = DEF_CHKINTR;
1604 defproxy.defsrv.check.fastinter = 0;
1605 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001606 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1607 defproxy.defsrv.agent.fastinter = 0;
1608 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001609 defproxy.defsrv.check.rise = DEF_RISETIME;
1610 defproxy.defsrv.check.fall = DEF_FALLTIME;
1611 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1612 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001613 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001614 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001615 defproxy.defsrv.maxqueue = 0;
1616 defproxy.defsrv.minconn = 0;
1617 defproxy.defsrv.maxconn = 0;
1618 defproxy.defsrv.slowstart = 0;
1619 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1620 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1621 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001622
1623 defproxy.email_alert.level = LOG_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001624}
1625
Willy Tarreauade5ec42010-01-28 19:33:49 +01001626
Willy Tarreau63af98d2014-05-18 08:11:41 +02001627/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1628 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1629 * ERR_FATAL in case of error.
1630 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001631static int create_cond_regex_rule(const char *file, int line,
1632 struct proxy *px, int dir, int action, int flags,
1633 const char *cmd, const char *reg, const char *repl,
1634 const char **cond_start)
1635{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001636 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001637 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001638 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001639 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001640 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001641 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001642 int cs;
1643 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001644
1645 if (px == &defproxy) {
1646 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001647 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001648 goto err;
1649 }
1650
1651 if (*reg == 0) {
1652 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001653 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001654 goto err;
1655 }
1656
1657 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001658 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001659
Willy Tarreau5321c422010-01-28 20:35:13 +01001660 if (cond_start &&
1661 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001662 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1663 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1664 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001665 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001666 goto err;
1667 }
1668 }
1669 else if (cond_start && **cond_start) {
1670 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1671 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001672 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001673 goto err;
1674 }
1675
Willy Tarreau63af98d2014-05-18 08:11:41 +02001676 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001677 (dir == SMP_OPT_DIR_REQ) ?
1678 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1679 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1680 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001681
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001682 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001683 if (!preg) {
1684 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001685 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001686 goto err;
1687 }
1688
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001689 cs = !(flags & REG_ICASE);
1690 cap = !(flags & REG_NOSUB);
1691 error = NULL;
1692 if (!regex_comp(reg, preg, cs, cap, &error)) {
1693 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1694 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001695 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001696 goto err;
1697 }
1698
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001699 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001700 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001701 if (repl && err) {
1702 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1703 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001704 ret_code |= ERR_ALERT | ERR_FATAL;
1705 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001706 }
1707
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001708 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001709 ret_code |= ERR_WARN;
1710
1711 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001712
Willy Tarreau63af98d2014-05-18 08:11:41 +02001713 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001714 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001715 err:
1716 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001717 free(errmsg);
1718 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001719}
1720
Willy Tarreaubaaee002006-06-26 02:48:02 +02001721/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001722 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001723 * Returns the error code, 0 if OK, or any combination of :
1724 * - ERR_ABORT: must abort ASAP
1725 * - ERR_FATAL: we can continue parsing but not start the service
1726 * - ERR_WARN: a warning has been emitted
1727 * - ERR_ALERT: an alert has been emitted
1728 * Only the two first ones can stop processing, the two others are just
1729 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001730 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001731int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1732{
1733 static struct peers *curpeers = NULL;
1734 struct peer *newpeer = NULL;
1735 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001736 struct bind_conf *bind_conf;
1737 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001738 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001739 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001740
1741 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001742 if (!*args[1]) {
1743 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001744 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001745 goto out;
1746 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001747
1748 err = invalid_char(args[1]);
1749 if (err) {
1750 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1751 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001752 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001753 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001754 }
1755
1756 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1757 /*
1758 * If there are two proxies with the same name only following
1759 * combinations are allowed:
1760 */
1761 if (strcmp(curpeers->id, args[1]) == 0) {
1762 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1763 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1764 err_code |= ERR_WARN;
1765 }
1766 }
1767
1768 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1769 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1770 err_code |= ERR_ALERT | ERR_ABORT;
1771 goto out;
1772 }
1773
1774 curpeers->next = peers;
1775 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001776 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001777 curpeers->conf.line = linenum;
1778 curpeers->last_change = now.tv_sec;
1779 curpeers->id = strdup(args[1]);
1780 }
1781 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001782 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001783 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001784 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001785
1786 if (!*args[2]) {
1787 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1788 file, linenum, args[0]);
1789 err_code |= ERR_ALERT | ERR_FATAL;
1790 goto out;
1791 }
1792
1793 err = invalid_char(args[1]);
1794 if (err) {
1795 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1796 file, linenum, *err, args[1]);
1797 err_code |= ERR_ALERT | ERR_FATAL;
1798 goto out;
1799 }
1800
1801 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1802 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1803 err_code |= ERR_ALERT | ERR_ABORT;
1804 goto out;
1805 }
1806
1807 /* the peers are linked backwards first */
1808 curpeers->count++;
1809 newpeer->next = curpeers->remote;
1810 curpeers->remote = newpeer;
1811 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001812 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001813 newpeer->conf.line = linenum;
1814
1815 newpeer->last_change = now.tv_sec;
1816 newpeer->id = strdup(args[1]);
1817
Willy Tarreau902636f2013-03-10 19:44:48 +01001818 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001819 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001820 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001821 err_code |= ERR_ALERT | ERR_FATAL;
1822 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001823 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001824
1825 proto = protocol_by_family(sk->ss_family);
1826 if (!proto || !proto->connect) {
1827 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1828 file, linenum, args[0], args[1]);
1829 err_code |= ERR_ALERT | ERR_FATAL;
1830 goto out;
1831 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001832
1833 if (port1 != port2) {
1834 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1835 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001836 err_code |= ERR_ALERT | ERR_FATAL;
1837 goto out;
1838 }
1839
Willy Tarreau2aa38802013-02-20 19:20:59 +01001840 if (!port1) {
1841 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1842 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001843 err_code |= ERR_ALERT | ERR_FATAL;
1844 goto out;
1845 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001846
Emeric Brun32da3c42010-09-23 18:39:19 +02001847 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001848 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001849 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001850 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001851
Emeric Brun32da3c42010-09-23 18:39:19 +02001852 if (strcmp(newpeer->id, localpeer) == 0) {
1853 /* Current is local peer, it define a frontend */
1854 newpeer->local = 1;
1855
1856 if (!curpeers->peers_fe) {
1857 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1858 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1859 err_code |= ERR_ALERT | ERR_ABORT;
1860 goto out;
1861 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001862
Willy Tarreau237250c2011-07-29 01:49:03 +02001863 init_new_proxy(curpeers->peers_fe);
1864 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001865 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001866 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1867 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01001868 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02001869
1870 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1871
Willy Tarreau902636f2013-03-10 19:44:48 +01001872 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1873 if (errmsg && *errmsg) {
1874 indent_msg(&errmsg, 2);
1875 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001876 }
1877 else
1878 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1879 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001880 err_code |= ERR_FATAL;
1881 goto out;
1882 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001883
1884 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001885 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001886 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1887 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02001888 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02001889 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001890 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01001891 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001892 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1893 global.maxsock += l->maxconn;
1894 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001895 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001896 else {
1897 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1898 file, linenum, args[0], args[1],
1899 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1900 err_code |= ERR_FATAL;
1901 goto out;
1902 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001903 }
1904 } /* neither "peer" nor "peers" */
1905 else if (*args[0] != 0) {
1906 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1907 err_code |= ERR_ALERT | ERR_FATAL;
1908 goto out;
1909 }
1910
1911out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001912 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001913 return err_code;
1914}
1915
Simon Horman0d16a402015-01-30 11:22:58 +09001916
1917/*
1918 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
1919 * Returns the error code, 0 if OK, or any combination of :
1920 * - ERR_ABORT: must abort ASAP
1921 * - ERR_FATAL: we can continue parsing but not start the service
1922 * - ERR_WARN: a warning has been emitted
1923 * - ERR_ALERT: an alert has been emitted
1924 * Only the two first ones can stop processing, the two others are just
1925 * indicators.
1926 */
1927int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
1928{
1929 static struct mailers *curmailers = NULL;
1930 struct mailer *newmailer = NULL;
1931 const char *err;
1932 int err_code = 0;
1933 char *errmsg = NULL;
1934
1935 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
1936 if (!*args[1]) {
1937 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
1938 err_code |= ERR_ALERT | ERR_ABORT;
1939 goto out;
1940 }
1941
1942 err = invalid_char(args[1]);
1943 if (err) {
1944 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1945 file, linenum, *err, args[0], args[1]);
1946 err_code |= ERR_ALERT | ERR_ABORT;
1947 goto out;
1948 }
1949
1950 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
1951 /*
1952 * If there are two proxies with the same name only following
1953 * combinations are allowed:
1954 */
1955 if (strcmp(curmailers->id, args[1]) == 0) {
1956 Warning("Parsing [%s:%d]: mailers '%s' has same name as another mailers (declared at %s:%d).\n",
1957 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
1958 err_code |= ERR_WARN;
1959 }
1960 }
1961
1962 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
1963 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1964 err_code |= ERR_ALERT | ERR_ABORT;
1965 goto out;
1966 }
1967
1968 curmailers->next = mailers;
1969 mailers = curmailers;
1970 curmailers->conf.file = strdup(file);
1971 curmailers->conf.line = linenum;
1972 curmailers->id = strdup(args[1]);
1973 }
1974 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
1975 struct sockaddr_storage *sk;
1976 int port1, port2;
1977 struct protocol *proto;
1978
1979 if (!*args[2]) {
1980 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1981 file, linenum, args[0]);
1982 err_code |= ERR_ALERT | ERR_FATAL;
1983 goto out;
1984 }
1985
1986 err = invalid_char(args[1]);
1987 if (err) {
1988 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1989 file, linenum, *err, args[1]);
1990 err_code |= ERR_ALERT | ERR_FATAL;
1991 goto out;
1992 }
1993
1994 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
1995 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1996 err_code |= ERR_ALERT | ERR_ABORT;
1997 goto out;
1998 }
1999
2000 /* the mailers are linked backwards first */
2001 curmailers->count++;
2002 newmailer->next = curmailers->mailer_list;
2003 curmailers->mailer_list = newmailer;
2004 newmailer->mailers = curmailers;
2005 newmailer->conf.file = strdup(file);
2006 newmailer->conf.line = linenum;
2007
2008 newmailer->id = strdup(args[1]);
2009
2010 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2011 if (!sk) {
2012 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2013 err_code |= ERR_ALERT | ERR_FATAL;
2014 goto out;
2015 }
2016
2017 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002018 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2019 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002020 file, linenum, args[0], args[1]);
2021 err_code |= ERR_ALERT | ERR_FATAL;
2022 goto out;
2023 }
2024
2025 if (port1 != port2) {
2026 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2027 file, linenum, args[0], args[1], args[2]);
2028 err_code |= ERR_ALERT | ERR_FATAL;
2029 goto out;
2030 }
2031
2032 if (!port1) {
2033 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2034 file, linenum, args[0], args[1], args[2]);
2035 err_code |= ERR_ALERT | ERR_FATAL;
2036 goto out;
2037 }
2038
2039 newmailer->addr = *sk;
2040 newmailer->proto = proto;
2041 newmailer->xprt = &raw_sock;
2042 newmailer->sock_init_arg = NULL;
2043 } /* neither "mailer" nor "mailers" */
2044 else if (*args[0] != 0) {
2045 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2046 err_code |= ERR_ALERT | ERR_FATAL;
2047 goto out;
2048 }
2049
2050out:
2051 free(errmsg);
2052 return err_code;
2053}
2054
Simon Horman9dc49962015-01-30 11:22:59 +09002055static void free_email_alert(struct proxy *p)
2056{
2057 free(p->email_alert.mailers.name);
2058 p->email_alert.mailers.name = NULL;
2059 free(p->email_alert.from);
2060 p->email_alert.from = NULL;
2061 free(p->email_alert.to);
2062 p->email_alert.to = NULL;
2063 free(p->email_alert.myhostname);
2064 p->email_alert.myhostname = NULL;
2065}
2066
Willy Tarreau3842f002009-06-14 11:39:52 +02002067int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002068{
2069 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002070 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002071 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002072 int rc;
2073 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002074 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002075 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002076 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002077 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002078 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002079
Willy Tarreau977b8e42006-12-29 14:19:17 +01002080 if (!strcmp(args[0], "listen"))
2081 rc = PR_CAP_LISTEN;
2082 else if (!strcmp(args[0], "frontend"))
2083 rc = PR_CAP_FE | PR_CAP_RS;
2084 else if (!strcmp(args[0], "backend"))
2085 rc = PR_CAP_BE | PR_CAP_RS;
2086 else if (!strcmp(args[0], "ruleset"))
2087 rc = PR_CAP_RS;
2088 else
2089 rc = PR_CAP_NONE;
2090
2091 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002092 struct ebpt_node *node;
2093
Willy Tarreaubaaee002006-06-26 02:48:02 +02002094 if (!*args[1]) {
2095 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2096 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2097 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002098 err_code |= ERR_ALERT | ERR_ABORT;
2099 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002100 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002101
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002102 err = invalid_char(args[1]);
2103 if (err) {
2104 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2105 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002106 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002107 }
2108
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002109 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
2110 curproxy = container_of(node, struct proxy, conf.by_name);
2111
2112 if (strcmp(curproxy->id, args[1]) != 0)
2113 break;
2114
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002115 /*
2116 * If there are two proxies with the same name only following
2117 * combinations are allowed:
2118 *
2119 * listen backend frontend ruleset
2120 * listen - - - -
2121 * backend - - OK -
2122 * frontend - OK - -
2123 * ruleset - - - -
2124 */
2125
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002126 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
2127 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02002128 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
2129 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2130 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02002131 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002132 }
2133 }
2134
Willy Tarreaubaaee002006-06-26 02:48:02 +02002135 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2136 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002137 err_code |= ERR_ALERT | ERR_ABORT;
2138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002139 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002140
Willy Tarreau97cb7802010-01-03 20:23:58 +01002141 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002142 curproxy->next = proxy;
2143 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002144 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2145 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002146 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002147 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002148 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002149 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002150
2151 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002152 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002153 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02002154
Willy Tarreau4348fad2012-09-20 16:48:07 +02002155 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2156
Willy Tarreau902636f2013-03-10 19:44:48 +01002157 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2158 if (errmsg && *errmsg) {
2159 indent_msg(&errmsg, 2);
2160 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002161 }
2162 else
2163 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2164 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002165 err_code |= ERR_FATAL;
2166 goto out;
2167 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002168
Willy Tarreau4348fad2012-09-20 16:48:07 +02002169 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002170 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002171 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002172 }
2173
2174 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002175 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002176 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002177
Willy Tarreaubaaee002006-06-26 02:48:02 +02002178 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002179 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002180 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002181 curproxy->no_options = defproxy.no_options;
2182 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002183 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002184 curproxy->except_net = defproxy.except_net;
2185 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002186 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002187 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002188
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002189 if (defproxy.fwdfor_hdr_len) {
2190 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2191 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2192 }
2193
Willy Tarreaub86db342009-11-30 11:50:16 +01002194 if (defproxy.orgto_hdr_len) {
2195 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2196 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2197 }
2198
Mark Lamourinec2247f02012-01-04 13:02:01 -05002199 if (defproxy.server_id_hdr_len) {
2200 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2201 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2202 }
2203
Willy Tarreau977b8e42006-12-29 14:19:17 +01002204 if (curproxy->cap & PR_CAP_FE) {
2205 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002206 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002207 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002208
2209 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002210 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2211 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002212
2213 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002215
Willy Tarreau977b8e42006-12-29 14:19:17 +01002216 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002217 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002218 curproxy->fullconn = defproxy.fullconn;
2219 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002220 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002221
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002222 if (defproxy.check_req) {
2223 curproxy->check_req = calloc(1, defproxy.check_len);
2224 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2225 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002226 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002227
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002228 if (defproxy.expect_str) {
2229 curproxy->expect_str = strdup(defproxy.expect_str);
2230 if (defproxy.expect_regex) {
2231 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002232 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2233 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002234 }
2235 }
2236
Willy Tarreau67402132012-05-31 20:40:20 +02002237 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002238 if (defproxy.cookie_name)
2239 curproxy->cookie_name = strdup(defproxy.cookie_name);
2240 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002241 if (defproxy.cookie_domain)
2242 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002243
Willy Tarreau31936852010-10-06 16:59:56 +02002244 if (defproxy.cookie_maxidle)
2245 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2246
2247 if (defproxy.cookie_maxlife)
2248 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2249
Emeric Brun647caf12009-06-30 17:57:00 +02002250 if (defproxy.rdp_cookie_name)
2251 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2252 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2253
Willy Tarreau01732802007-11-01 22:48:15 +01002254 if (defproxy.url_param_name)
2255 curproxy->url_param_name = strdup(defproxy.url_param_name);
2256 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002257
Benoitaffb4812009-03-25 13:02:10 +01002258 if (defproxy.hh_name)
2259 curproxy->hh_name = strdup(defproxy.hh_name);
2260 curproxy->hh_len = defproxy.hh_len;
2261 curproxy->hh_match_domain = defproxy.hh_match_domain;
2262
Willy Tarreauef9a3602012-12-08 22:29:20 +01002263 if (defproxy.conn_src.iface_name)
2264 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2265 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002266 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002267#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002268 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002269#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002270 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002271
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002272 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002273 if (defproxy.capture_name)
2274 curproxy->capture_name = strdup(defproxy.capture_name);
2275 curproxy->capture_namelen = defproxy.capture_namelen;
2276 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002277 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002278
Willy Tarreau977b8e42006-12-29 14:19:17 +01002279 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002280 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002281 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002282 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002283 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002284 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002285 curproxy->mon_net = defproxy.mon_net;
2286 curproxy->mon_mask = defproxy.mon_mask;
2287 if (defproxy.monitor_uri)
2288 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2289 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002290 if (defproxy.defbe.name)
2291 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002292
2293 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002294 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2295 if (curproxy->conf.logformat_string &&
2296 curproxy->conf.logformat_string != default_http_log_format &&
2297 curproxy->conf.logformat_string != default_tcp_log_format &&
2298 curproxy->conf.logformat_string != clf_http_log_format)
2299 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2300
2301 if (defproxy.conf.lfs_file) {
2302 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2303 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2304 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002305 }
2306
2307 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002308 curproxy->timeout.connect = defproxy.timeout.connect;
2309 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002310 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002311 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002312 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002313 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002314 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002315 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002316 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002317 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002318 }
2319
Willy Tarreaubaaee002006-06-26 02:48:02 +02002320 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002321 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002322
2323 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002324 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002325 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002326 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002327 LIST_INIT(&node->list);
2328 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2329 }
2330
Willy Tarreau62a61232013-04-12 18:13:46 +02002331 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2332 if (curproxy->conf.uniqueid_format_string)
2333 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2334
Willy Tarreau094af4e2015-01-07 15:03:42 +01002335 if (defproxy.log_tag)
2336 curproxy->log_tag = strdup(defproxy.log_tag);
2337
Willy Tarreau62a61232013-04-12 18:13:46 +02002338 if (defproxy.conf.uif_file) {
2339 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2340 curproxy->conf.uif_line = defproxy.conf.uif_line;
2341 }
William Lallemanda73203e2012-03-12 12:48:57 +01002342
2343 /* copy default header unique id */
2344 if (defproxy.header_unique_id)
2345 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2346
William Lallemand82fe75c2012-10-23 10:25:10 +02002347 /* default compression options */
2348 if (defproxy.comp != NULL) {
2349 curproxy->comp = calloc(1, sizeof(struct comp));
2350 curproxy->comp->algos = defproxy.comp->algos;
2351 curproxy->comp->types = defproxy.comp->types;
2352 }
2353
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002355 curproxy->conf.used_listener_id = EB_ROOT;
2356 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002357
Simon Horman98637e52014-06-20 12:30:16 +09002358 if (defproxy.check_path)
2359 curproxy->check_path = strdup(defproxy.check_path);
2360 if (defproxy.check_command)
2361 curproxy->check_command = strdup(defproxy.check_command);
2362
Simon Horman9dc49962015-01-30 11:22:59 +09002363 if (defproxy.email_alert.mailers.name)
2364 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2365 if (defproxy.email_alert.from)
2366 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2367 if (defproxy.email_alert.to)
2368 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2369 if (defproxy.email_alert.myhostname)
2370 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002371 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002372
Willy Tarreau93893792009-07-23 13:19:11 +02002373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002374 }
2375 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2376 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002377 /* FIXME-20070101: we should do this too at the end of the
2378 * config parsing to free all default values.
2379 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002380 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002381 free(defproxy.check_command);
2382 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002383 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002384 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002385 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002386 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002387 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002388 free(defproxy.capture_name);
2389 free(defproxy.monitor_uri);
2390 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002391 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002392 free(defproxy.fwdfor_hdr_name);
2393 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002394 free(defproxy.orgto_hdr_name);
2395 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002396 free(defproxy.server_id_hdr_name);
2397 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002398 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002399 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002400 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002401 free(defproxy.expect_regex);
2402 defproxy.expect_regex = NULL;
2403 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002404
Willy Tarreau62a61232013-04-12 18:13:46 +02002405 if (defproxy.conf.logformat_string != default_http_log_format &&
2406 defproxy.conf.logformat_string != default_tcp_log_format &&
2407 defproxy.conf.logformat_string != clf_http_log_format)
2408 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002409
Willy Tarreau62a61232013-04-12 18:13:46 +02002410 free(defproxy.conf.uniqueid_format_string);
2411 free(defproxy.conf.lfs_file);
2412 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002413 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002414 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002415
Willy Tarreaua534fea2008-08-03 12:19:50 +02002416 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002417 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002418
Willy Tarreaubaaee002006-06-26 02:48:02 +02002419 /* we cannot free uri_auth because it might already be used */
2420 init_default_instance();
2421 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002422 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2423 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002424 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 }
2427 else if (curproxy == NULL) {
2428 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002432
2433 /* update the current file and line being parsed */
2434 curproxy->conf.args.file = curproxy->conf.file;
2435 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002436
2437 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002438 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2439 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2440 if (err_code & ERR_FATAL)
2441 goto out;
2442 }
2443 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002444 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002445 int cur_arg;
2446
Willy Tarreaubaaee002006-06-26 02:48:02 +02002447 if (curproxy == &defproxy) {
2448 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002449 err_code |= ERR_ALERT | ERR_FATAL;
2450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002452 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002453 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002454
Willy Tarreau24709282013-03-10 21:32:12 +01002455 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002456 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002457 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002458 err_code |= ERR_ALERT | ERR_FATAL;
2459 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002461
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002462 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002463
2464 /* use default settings for unix sockets */
2465 bind_conf->ux.uid = global.unix_bind.ux.uid;
2466 bind_conf->ux.gid = global.unix_bind.ux.gid;
2467 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002468
2469 /* NOTE: the following line might create several listeners if there
2470 * are comma-separated IPs or port ranges. So all further processing
2471 * will have to be applied to all listeners created after last_listen.
2472 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002473 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2474 if (errmsg && *errmsg) {
2475 indent_msg(&errmsg, 2);
2476 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002477 }
2478 else
2479 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2480 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002481 err_code |= ERR_ALERT | ERR_FATAL;
2482 goto out;
2483 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002484
Willy Tarreau4348fad2012-09-20 16:48:07 +02002485 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2486 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002487 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002488 }
2489
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002490 cur_arg = 2;
2491 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002492 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002493 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002494 char *err;
2495
Willy Tarreau26982662012-09-12 23:17:10 +02002496 kw = bind_find_kw(args[cur_arg]);
2497 if (kw) {
2498 char *err = NULL;
2499 int code;
2500
2501 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002502 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2503 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002504 cur_arg += 1 + kw->skip ;
2505 err_code |= ERR_ALERT | ERR_FATAL;
2506 goto out;
2507 }
2508
Willy Tarreau4348fad2012-09-20 16:48:07 +02002509 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002510 err_code |= code;
2511
2512 if (code) {
2513 if (err && *err) {
2514 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002515 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002516 }
2517 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002518 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2519 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002520 if (code & ERR_FATAL) {
2521 free(err);
2522 cur_arg += 1 + kw->skip;
2523 goto out;
2524 }
2525 }
2526 free(err);
2527 cur_arg += 1 + kw->skip;
2528 continue;
2529 }
2530
Willy Tarreau8638f482012-09-18 18:01:17 +02002531 err = NULL;
2532 if (!bind_dumped) {
2533 bind_dump_kws(&err);
2534 indent_msg(&err, 4);
2535 bind_dumped = 1;
2536 }
2537
2538 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2539 file, linenum, args[0], args[1], args[cur_arg],
2540 err ? " Registered keywords :" : "", err ? err : "");
2541 free(err);
2542
Willy Tarreau93893792009-07-23 13:19:11 +02002543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002545 }
Willy Tarreau93893792009-07-23 13:19:11 +02002546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547 }
2548 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002549 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2551 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002552 err_code |= ERR_ALERT | ERR_FATAL;
2553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002554 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002555 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002556 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002557
Willy Tarreaubaaee002006-06-26 02:48:02 +02002558 /* flush useless bits */
2559 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002562 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002563 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002564 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002565
Willy Tarreau1c47f852006-07-09 08:22:27 +02002566 if (!*args[1]) {
2567 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2568 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_ALERT | ERR_FATAL;
2570 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002571 }
2572
Willy Tarreaua534fea2008-08-03 12:19:50 +02002573 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002574 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002575 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002576 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002577 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2578
Willy Tarreau93893792009-07-23 13:19:11 +02002579 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002580 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2582 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2583 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2584 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2585 else {
2586 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002587 err_code |= ERR_ALERT | ERR_FATAL;
2588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 }
2590 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002591 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002592 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002593
2594 if (curproxy == &defproxy) {
2595 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2596 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002597 err_code |= ERR_ALERT | ERR_FATAL;
2598 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002599 }
2600
2601 if (!*args[1]) {
2602 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2603 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002604 err_code |= ERR_ALERT | ERR_FATAL;
2605 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002606 }
2607
2608 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002609 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002610
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002611 if (curproxy->uuid <= 0) {
2612 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002613 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002616 }
2617
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002618 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2619 if (node) {
2620 struct proxy *target = container_of(node, struct proxy, conf.id);
2621 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2622 file, linenum, proxy_type_str(curproxy), curproxy->id,
2623 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
2626 }
2627 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002628 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002629 else if (!strcmp(args[0], "description")) {
2630 int i, len=0;
2631 char *d;
2632
Cyril Bonté99ed3272010-01-24 23:29:44 +01002633 if (curproxy == &defproxy) {
2634 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2635 file, linenum, args[0]);
2636 err_code |= ERR_ALERT | ERR_FATAL;
2637 goto out;
2638 }
2639
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002640 if (!*args[1]) {
2641 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2642 file, linenum, args[0]);
2643 return -1;
2644 }
2645
Willy Tarreau348acfe2014-04-14 15:00:39 +02002646 for (i = 1; *args[i]; i++)
2647 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002648
2649 d = (char *)calloc(1, len);
2650 curproxy->desc = d;
2651
Willy Tarreau348acfe2014-04-14 15:00:39 +02002652 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2653 for (i = 2; *args[i]; i++)
2654 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002655
2656 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002657 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2658 curproxy->state = PR_STSTOPPED;
2659 }
2660 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2661 curproxy->state = PR_STNEW;
2662 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002663 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2664 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002665 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002666
2667 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002668 unsigned int low, high;
2669
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002670 if (strcmp(args[cur_arg], "all") == 0) {
2671 set = 0;
2672 break;
2673 }
2674 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002675 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002676 }
2677 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002678 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002679 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002680 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002681 char *dash = strchr(args[cur_arg], '-');
2682
2683 low = high = str2uic(args[cur_arg]);
2684 if (dash)
2685 high = str2uic(dash + 1);
2686
2687 if (high < low) {
2688 unsigned int swap = low;
2689 low = high;
2690 high = swap;
2691 }
2692
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002693 if (low < 1 || high > LONGBITS) {
2694 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2695 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002696 err_code |= ERR_ALERT | ERR_FATAL;
2697 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002698 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002699 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002700 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002701 }
2702 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002703 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2704 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002705 err_code |= ERR_ALERT | ERR_FATAL;
2706 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002707 }
2708 cur_arg++;
2709 }
2710 curproxy->bind_proc = set;
2711 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002712 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002713 if (curproxy == &defproxy) {
2714 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002715 err_code |= ERR_ALERT | ERR_FATAL;
2716 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002717 }
2718
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002719 err = invalid_char(args[1]);
2720 if (err) {
2721 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2722 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002723 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002724 }
2725
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002726 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002727 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2728 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002729 err_code |= ERR_ALERT | ERR_FATAL;
2730 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002731 }
2732 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002733 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2734 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002735
Willy Tarreau977b8e42006-12-29 14:19:17 +01002736 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002737 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002738
Willy Tarreaubaaee002006-06-26 02:48:02 +02002739 if (*(args[1]) == 0) {
2740 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2741 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002742 err_code |= ERR_ALERT | ERR_FATAL;
2743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002744 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002745
Willy Tarreau67402132012-05-31 20:40:20 +02002746 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002747 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002748 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002749 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002750 curproxy->cookie_name = strdup(args[1]);
2751 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002752
Willy Tarreaubaaee002006-06-26 02:48:02 +02002753 cur_arg = 2;
2754 while (*(args[cur_arg])) {
2755 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002756 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002757 }
2758 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002759 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002760 }
2761 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002762 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 }
2764 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002765 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002766 }
2767 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002768 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002769 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002770 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002771 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002772 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002773 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002774 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002775 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002776 else if (!strcmp(args[cur_arg], "httponly")) {
2777 curproxy->ck_opts |= PR_CK_HTTPONLY;
2778 }
2779 else if (!strcmp(args[cur_arg], "secure")) {
2780 curproxy->ck_opts |= PR_CK_SECURE;
2781 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002782 else if (!strcmp(args[cur_arg], "domain")) {
2783 if (!*args[cur_arg + 1]) {
2784 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2785 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002786 err_code |= ERR_ALERT | ERR_FATAL;
2787 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002788 }
2789
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002790 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002791 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002792 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2793 " dots nor does not start with a dot."
2794 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002795 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002796 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002797 }
2798
2799 err = invalid_domainchar(args[cur_arg + 1]);
2800 if (err) {
2801 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2802 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002803 err_code |= ERR_ALERT | ERR_FATAL;
2804 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002805 }
2806
Willy Tarreau68a897b2009-12-03 23:28:34 +01002807 if (!curproxy->cookie_domain) {
2808 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2809 } else {
2810 /* one domain was already specified, add another one by
2811 * building the string which will be returned along with
2812 * the cookie.
2813 */
2814 char *new_ptr;
2815 int new_len = strlen(curproxy->cookie_domain) +
2816 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2817 new_ptr = malloc(new_len);
2818 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2819 free(curproxy->cookie_domain);
2820 curproxy->cookie_domain = new_ptr;
2821 }
Willy Tarreau31936852010-10-06 16:59:56 +02002822 cur_arg++;
2823 }
2824 else if (!strcmp(args[cur_arg], "maxidle")) {
2825 unsigned int maxidle;
2826 const char *res;
2827
2828 if (!*args[cur_arg + 1]) {
2829 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2830 file, linenum, args[cur_arg]);
2831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
2833 }
2834
2835 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2836 if (res) {
2837 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2838 file, linenum, *res, args[cur_arg]);
2839 err_code |= ERR_ALERT | ERR_FATAL;
2840 goto out;
2841 }
2842 curproxy->cookie_maxidle = maxidle;
2843 cur_arg++;
2844 }
2845 else if (!strcmp(args[cur_arg], "maxlife")) {
2846 unsigned int maxlife;
2847 const char *res;
2848
2849 if (!*args[cur_arg + 1]) {
2850 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2851 file, linenum, args[cur_arg]);
2852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
2854 }
2855
2856 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2857 if (res) {
2858 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2859 file, linenum, *res, args[cur_arg]);
2860 err_code |= ERR_ALERT | ERR_FATAL;
2861 goto out;
2862 }
2863 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002864 cur_arg++;
2865 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002866 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002867 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 +02002868 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002869 err_code |= ERR_ALERT | ERR_FATAL;
2870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002871 }
2872 cur_arg++;
2873 }
Willy Tarreau67402132012-05-31 20:40:20 +02002874 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002875 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2876 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002877 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002878 }
2879
Willy Tarreau67402132012-05-31 20:40:20 +02002880 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002881 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2882 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002883 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002884 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002885
Willy Tarreau67402132012-05-31 20:40:20 +02002886 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002887 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2888 file, linenum);
2889 err_code |= ERR_ALERT | ERR_FATAL;
2890 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002891 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09002892 else if (!strcmp(args[0], "email-alert")) {
2893 if (*(args[1]) == 0) {
2894 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2895 file, linenum, args[0]);
2896 err_code |= ERR_ALERT | ERR_FATAL;
2897 goto out;
2898 }
2899
2900 if (!strcmp(args[1], "from")) {
2901 if (*(args[1]) == 0) {
2902 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2903 file, linenum, args[1]);
2904 err_code |= ERR_ALERT | ERR_FATAL;
2905 goto out;
2906 }
2907 free(curproxy->email_alert.from);
2908 curproxy->email_alert.from = strdup(args[2]);
2909 }
2910 else if (!strcmp(args[1], "mailers")) {
2911 if (*(args[1]) == 0) {
2912 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2913 file, linenum, args[1]);
2914 err_code |= ERR_ALERT | ERR_FATAL;
2915 goto out;
2916 }
2917 free(curproxy->email_alert.mailers.name);
2918 curproxy->email_alert.mailers.name = strdup(args[2]);
2919 }
2920 else if (!strcmp(args[1], "myhostname")) {
2921 if (*(args[1]) == 0) {
2922 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2923 file, linenum, args[1]);
2924 err_code |= ERR_ALERT | ERR_FATAL;
2925 goto out;
2926 }
2927 free(curproxy->email_alert.myhostname);
2928 curproxy->email_alert.myhostname = strdup(args[2]);
2929 }
Simon Horman64e34162015-02-06 11:11:57 +09002930 else if (!strcmp(args[1], "level")) {
2931 curproxy->email_alert.level = get_log_level(args[2]);
2932 if (curproxy->email_alert.level < 0) {
2933 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
2934 file, linenum, args[1], args[2]);
2935 err_code |= ERR_ALERT | ERR_FATAL;
2936 goto out;
2937 }
2938 }
Simon Horman9dc49962015-01-30 11:22:59 +09002939 else if (!strcmp(args[1], "to")) {
2940 if (*(args[1]) == 0) {
2941 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2942 file, linenum, args[1]);
2943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
2945 }
2946 free(curproxy->email_alert.to);
2947 curproxy->email_alert.to = strdup(args[2]);
2948 }
2949 else {
2950 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
2951 file, linenum, args[1]);
2952 err_code |= ERR_ALERT | ERR_FATAL;
2953 goto out;
2954 }
Simon Horman64e34162015-02-06 11:11:57 +09002955 /* Indicate that the email_alert is at least partially configured */
2956 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09002957 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09002958 else if (!strcmp(args[0], "external-check")) {
2959 if (*(args[1]) == 0) {
2960 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2961 file, linenum, args[0]);
2962 err_code |= ERR_ALERT | ERR_FATAL;
2963 goto out;
2964 }
2965
2966 if (!strcmp(args[1], "command")) {
2967 if (*(args[1]) == 0) {
2968 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2969 file, linenum, args[1]);
2970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
2972 }
2973 free(curproxy->check_command);
2974 curproxy->check_command = strdup(args[2]);
2975 }
2976 else if (!strcmp(args[1], "path")) {
2977 if (*(args[1]) == 0) {
2978 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2979 file, linenum, args[1]);
2980 err_code |= ERR_ALERT | ERR_FATAL;
2981 goto out;
2982 }
2983 free(curproxy->check_path);
2984 curproxy->check_path = strdup(args[2]);
2985 }
2986 else {
2987 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
2988 file, linenum, args[1]);
2989 err_code |= ERR_ALERT | ERR_FATAL;
2990 goto out;
2991 }
2992 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002993 else if (!strcmp(args[0], "persist")) { /* persist */
2994 if (*(args[1]) == 0) {
2995 Alert("parsing [%s:%d] : missing persist method.\n",
2996 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002997 err_code |= ERR_ALERT | ERR_FATAL;
2998 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002999 }
3000
3001 if (!strncmp(args[1], "rdp-cookie", 10)) {
3002 curproxy->options2 |= PR_O2_RDPC_PRST;
3003
Emeric Brunb982a3d2010-01-04 15:45:53 +01003004 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003005 const char *beg, *end;
3006
3007 beg = args[1] + 11;
3008 end = strchr(beg, ')');
3009
3010 if (!end || end == beg) {
3011 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3012 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003013 err_code |= ERR_ALERT | ERR_FATAL;
3014 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003015 }
3016
3017 free(curproxy->rdp_cookie_name);
3018 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3019 curproxy->rdp_cookie_len = end-beg;
3020 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003021 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003022 free(curproxy->rdp_cookie_name);
3023 curproxy->rdp_cookie_name = strdup("msts");
3024 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3025 }
3026 else { /* syntax */
3027 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3028 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003029 err_code |= ERR_ALERT | ERR_FATAL;
3030 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003031 }
3032 }
3033 else {
3034 Alert("parsing [%s:%d] : unknown persist method.\n",
3035 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003038 }
3039 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003041 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003042
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003043 if (curproxy == &defproxy) {
3044 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
3047 }
3048
Willy Tarreau977b8e42006-12-29 14:19:17 +01003049 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003050 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003051
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003053 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003054 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003057 }
3058 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003059 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003060 curproxy->appsession_name = strdup(args[1]);
3061 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3062 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003063 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3064 if (err) {
3065 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3066 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003067 err_code |= ERR_ALERT | ERR_FATAL;
3068 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003069 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003070 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003071
Willy Tarreau51041c72007-09-09 21:56:53 +02003072 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3073 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003074 err_code |= ERR_ALERT | ERR_ABORT;
3075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003076 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003077
3078 cur_arg = 6;
3079 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003080 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3081 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003082 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003083 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003084 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003085 } else if (!strcmp(args[cur_arg], "prefix")) {
3086 curproxy->options2 |= PR_O2_AS_PFX;
3087 } else if (!strcmp(args[cur_arg], "mode")) {
3088 if (!*args[cur_arg + 1]) {
3089 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3090 file, linenum, args[0], args[cur_arg]);
3091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
3093 }
3094
3095 cur_arg++;
3096 if (!strcmp(args[cur_arg], "query-string")) {
3097 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3098 curproxy->options2 |= PR_O2_AS_M_QS;
3099 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3100 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3101 curproxy->options2 |= PR_O2_AS_M_PP;
3102 } else {
3103 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3104 err_code |= ERR_ALERT | ERR_FATAL;
3105 goto out;
3106 }
3107 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003108 cur_arg++;
3109 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003110 } /* Url App Session */
3111 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003112 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003113 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003114
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003116 if (curproxy == &defproxy) {
3117 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3118 err_code |= ERR_ALERT | ERR_FATAL;
3119 goto out;
3120 }
3121
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 if (*(args[4]) == 0) {
3123 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3124 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003127 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003128 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003129 curproxy->capture_name = strdup(args[2]);
3130 curproxy->capture_namelen = strlen(curproxy->capture_name);
3131 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 curproxy->to_log |= LW_COOKIE;
3133 }
3134 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3135 struct cap_hdr *hdr;
3136
3137 if (curproxy == &defproxy) {
3138 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 +02003139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003141 }
3142
3143 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3144 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3145 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003146 err_code |= ERR_ALERT | ERR_FATAL;
3147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 }
3149
3150 hdr = calloc(sizeof(struct cap_hdr), 1);
3151 hdr->next = curproxy->req_cap;
3152 hdr->name = strdup(args[3]);
3153 hdr->namelen = strlen(args[3]);
3154 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003155 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003156 hdr->index = curproxy->nb_req_cap++;
3157 curproxy->req_cap = hdr;
3158 curproxy->to_log |= LW_REQHDR;
3159 }
3160 else if (!strcmp(args[1], "response") && !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 hdr = calloc(sizeof(struct cap_hdr), 1);
3176 hdr->next = curproxy->rsp_cap;
3177 hdr->name = strdup(args[3]);
3178 hdr->namelen = strlen(args[3]);
3179 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003180 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 hdr->index = curproxy->nb_rsp_cap++;
3182 curproxy->rsp_cap = hdr;
3183 curproxy->to_log |= LW_RSPHDR;
3184 }
3185 else {
3186 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3187 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003188 err_code |= ERR_ALERT | ERR_FATAL;
3189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003190 }
3191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003193 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003194 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003195
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 if (*(args[1]) == 0) {
3197 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3198 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003199 err_code |= ERR_ALERT | ERR_FATAL;
3200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 }
3202 curproxy->conn_retries = atol(args[1]);
3203 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003204 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003205 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003206
3207 if (curproxy == &defproxy) {
3208 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3209 err_code |= ERR_ALERT | ERR_FATAL;
3210 goto out;
3211 }
3212
Willy Tarreau20b0de52012-12-24 15:45:22 +01003213 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3214 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3215 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3216 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003217 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003218 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3219 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 +01003220 file, linenum, args[0]);
3221 err_code |= ERR_WARN;
3222 }
3223
Willy Tarreauff011f22011-01-06 17:51:27 +01003224 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003225
Willy Tarreauff011f22011-01-06 17:51:27 +01003226 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003227 err_code |= ERR_ALERT | ERR_ABORT;
3228 goto out;
3229 }
3230
Willy Tarreau5002f572014-04-23 01:32:02 +02003231 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003232 err_code |= warnif_cond_conflicts(rule->cond,
3233 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3234 file, linenum);
3235
Willy Tarreauff011f22011-01-06 17:51:27 +01003236 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003237 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003238 else if (!strcmp(args[0], "http-response")) { /* response access control */
3239 struct http_res_rule *rule;
3240
3241 if (curproxy == &defproxy) {
3242 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3243 err_code |= ERR_ALERT | ERR_FATAL;
3244 goto out;
3245 }
3246
3247 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3248 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3249 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3250 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3251 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3252 file, linenum, args[0]);
3253 err_code |= ERR_WARN;
3254 }
3255
3256 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3257
3258 if (!rule) {
3259 err_code |= ERR_ALERT | ERR_ABORT;
3260 goto out;
3261 }
3262
3263 err_code |= warnif_cond_conflicts(rule->cond,
3264 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3265 file, linenum);
3266
3267 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3268 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003269 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3270 /* set the header name and length into the proxy structure */
3271 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3272 err_code |= ERR_WARN;
3273
3274 if (!*args[1]) {
3275 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3276 file, linenum, args[0]);
3277 err_code |= ERR_ALERT | ERR_FATAL;
3278 goto out;
3279 }
3280
3281 /* set the desired header name */
3282 free(curproxy->server_id_hdr_name);
3283 curproxy->server_id_hdr_name = strdup(args[1]);
3284 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3285 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003286 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003287 struct http_req_rule *rule;
3288
Willy Tarreaub099aca2008-10-12 17:26:37 +02003289 if (curproxy == &defproxy) {
3290 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003291 err_code |= ERR_ALERT | ERR_FATAL;
3292 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003293 }
3294
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003295 /* emulate "block" using "http-request block". Since these rules are supposed to
3296 * be processed before all http-request rules, we put them into their own list
3297 * and will insert them at the end.
3298 */
3299 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3300 if (!rule) {
3301 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003302 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003303 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003304 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3305 err_code |= warnif_cond_conflicts(rule->cond,
3306 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3307 file, linenum);
3308 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003309
3310 if (!already_warned(WARN_BLOCK_DEPRECATED))
3311 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]);
3312
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003313 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003314 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003315 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003316
Cyril Bonté99ed3272010-01-24 23:29:44 +01003317 if (curproxy == &defproxy) {
3318 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3319 err_code |= ERR_ALERT | ERR_FATAL;
3320 goto out;
3321 }
3322
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003323 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003324 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3325 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003326 err_code |= ERR_ALERT | ERR_FATAL;
3327 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003328 }
3329
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003330 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003331 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003332 err_code |= warnif_cond_conflicts(rule->cond,
3333 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3334 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003335 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003336 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003337 struct switching_rule *rule;
3338
Willy Tarreaub099aca2008-10-12 17:26:37 +02003339 if (curproxy == &defproxy) {
3340 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003341 err_code |= ERR_ALERT | ERR_FATAL;
3342 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003343 }
3344
Willy Tarreau55ea7572007-06-17 19:56:27 +02003345 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003346 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003347
3348 if (*(args[1]) == 0) {
3349 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003352 }
3353
Willy Tarreauf51658d2014-04-23 01:21:56 +02003354 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3355 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3356 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3357 file, linenum, errmsg);
3358 err_code |= ERR_ALERT | ERR_FATAL;
3359 goto out;
3360 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003361
Willy Tarreauf51658d2014-04-23 01:21:56 +02003362 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003363 }
3364
3365 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3366 rule->cond = cond;
3367 rule->be.name = strdup(args[1]);
3368 LIST_INIT(&rule->list);
3369 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3370 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003371 else if (strcmp(args[0], "use-server") == 0) {
3372 struct server_rule *rule;
3373
3374 if (curproxy == &defproxy) {
3375 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3376 err_code |= ERR_ALERT | ERR_FATAL;
3377 goto out;
3378 }
3379
3380 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3381 err_code |= ERR_WARN;
3382
3383 if (*(args[1]) == 0) {
3384 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3385 err_code |= ERR_ALERT | ERR_FATAL;
3386 goto out;
3387 }
3388
3389 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3390 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3391 file, linenum, args[0]);
3392 err_code |= ERR_ALERT | ERR_FATAL;
3393 goto out;
3394 }
3395
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003396 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3397 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3398 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003399 err_code |= ERR_ALERT | ERR_FATAL;
3400 goto out;
3401 }
3402
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003403 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003404
3405 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3406 rule->cond = cond;
3407 rule->srv.name = strdup(args[1]);
3408 LIST_INIT(&rule->list);
3409 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3410 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3411 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003412 else if ((!strcmp(args[0], "force-persist")) ||
3413 (!strcmp(args[0], "ignore-persist"))) {
3414 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003415
3416 if (curproxy == &defproxy) {
3417 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3418 err_code |= ERR_ALERT | ERR_FATAL;
3419 goto out;
3420 }
3421
3422 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3423 err_code |= ERR_WARN;
3424
Willy Tarreauef6494c2010-01-28 17:12:36 +01003425 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003426 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3427 file, linenum, args[0]);
3428 err_code |= ERR_ALERT | ERR_FATAL;
3429 goto out;
3430 }
3431
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003432 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3433 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3434 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003435 err_code |= ERR_ALERT | ERR_FATAL;
3436 goto out;
3437 }
3438
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003439 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3440 * where force-persist is applied.
3441 */
3442 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003443
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003444 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003445 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003446 if (!strcmp(args[0], "force-persist")) {
3447 rule->type = PERSIST_TYPE_FORCE;
3448 } else {
3449 rule->type = PERSIST_TYPE_IGNORE;
3450 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003451 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003452 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003453 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003454 else if (!strcmp(args[0], "stick-table")) {
3455 int myidx = 1;
3456
Emeric Brun32da3c42010-09-23 18:39:19 +02003457 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003458 curproxy->table.type = (unsigned int)-1;
3459 while (*args[myidx]) {
3460 const char *err;
3461
3462 if (strcmp(args[myidx], "size") == 0) {
3463 myidx++;
3464 if (!*(args[myidx])) {
3465 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3466 file, linenum, args[myidx-1]);
3467 err_code |= ERR_ALERT | ERR_FATAL;
3468 goto out;
3469 }
3470 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3471 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3472 file, linenum, *err, args[myidx-1]);
3473 err_code |= ERR_ALERT | ERR_FATAL;
3474 goto out;
3475 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003476 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003477 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003478 else if (strcmp(args[myidx], "peers") == 0) {
3479 myidx++;
Godbach50523162013-12-11 19:48:57 +08003480 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003481 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3482 file, linenum, args[myidx-1]);
3483 err_code |= ERR_ALERT | ERR_FATAL;
3484 goto out;
Godbach50523162013-12-11 19:48:57 +08003485 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003486 curproxy->table.peers.name = strdup(args[myidx++]);
3487 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003488 else if (strcmp(args[myidx], "expire") == 0) {
3489 myidx++;
3490 if (!*(args[myidx])) {
3491 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3492 file, linenum, args[myidx-1]);
3493 err_code |= ERR_ALERT | ERR_FATAL;
3494 goto out;
3495 }
3496 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3497 if (err) {
3498 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3499 file, linenum, *err, args[myidx-1]);
3500 err_code |= ERR_ALERT | ERR_FATAL;
3501 goto out;
3502 }
3503 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003504 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003505 }
3506 else if (strcmp(args[myidx], "nopurge") == 0) {
3507 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003508 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003509 }
3510 else if (strcmp(args[myidx], "type") == 0) {
3511 myidx++;
3512 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3513 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3514 file, linenum, args[myidx]);
3515 err_code |= ERR_ALERT | ERR_FATAL;
3516 goto out;
3517 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003518 /* myidx already points to next arg */
3519 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003520 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003521 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003522 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003523
3524 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003525 nw = args[myidx];
3526 while (*nw) {
3527 /* the "store" keyword supports a comma-separated list */
3528 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003529 sa = NULL; /* store arg */
3530 while (*nw && *nw != ',') {
3531 if (*nw == '(') {
3532 *nw = 0;
3533 sa = ++nw;
3534 while (*nw != ')') {
3535 if (!*nw) {
3536 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3537 file, linenum, args[0], cw);
3538 err_code |= ERR_ALERT | ERR_FATAL;
3539 goto out;
3540 }
3541 nw++;
3542 }
3543 *nw = '\0';
3544 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003545 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003546 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003547 if (*nw)
3548 *nw++ = '\0';
3549 type = stktable_get_data_type(cw);
3550 if (type < 0) {
3551 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3552 file, linenum, args[0], cw);
3553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
3555 }
Willy Tarreauac782882010-06-20 10:41:54 +02003556
3557 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3558 switch (err) {
3559 case PE_NONE: break;
3560 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003561 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3562 file, linenum, args[0], cw);
3563 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003564 break;
3565
3566 case PE_ARG_MISSING:
3567 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3568 file, linenum, args[0], cw);
3569 err_code |= ERR_ALERT | ERR_FATAL;
3570 goto out;
3571
3572 case PE_ARG_NOT_USED:
3573 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3574 file, linenum, args[0], cw);
3575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
3577
3578 default:
3579 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3580 file, linenum, args[0], cw);
3581 err_code |= ERR_ALERT | ERR_FATAL;
3582 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003583 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003584 }
3585 myidx++;
3586 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003587 else {
3588 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3589 file, linenum, args[myidx]);
3590 err_code |= ERR_ALERT | ERR_FATAL;
3591 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003592 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003593 }
3594
3595 if (!curproxy->table.size) {
3596 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3597 file, linenum);
3598 err_code |= ERR_ALERT | ERR_FATAL;
3599 goto out;
3600 }
3601
3602 if (curproxy->table.type == (unsigned int)-1) {
3603 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3604 file, linenum);
3605 err_code |= ERR_ALERT | ERR_FATAL;
3606 goto out;
3607 }
3608 }
3609 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003610 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003611 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003612 int myidx = 0;
3613 const char *name = NULL;
3614 int flags;
3615
3616 if (curproxy == &defproxy) {
3617 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3618 err_code |= ERR_ALERT | ERR_FATAL;
3619 goto out;
3620 }
3621
3622 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3623 err_code |= ERR_WARN;
3624 goto out;
3625 }
3626
3627 myidx++;
3628 if ((strcmp(args[myidx], "store") == 0) ||
3629 (strcmp(args[myidx], "store-request") == 0)) {
3630 myidx++;
3631 flags = STK_IS_STORE;
3632 }
3633 else if (strcmp(args[myidx], "store-response") == 0) {
3634 myidx++;
3635 flags = STK_IS_STORE | STK_ON_RSP;
3636 }
3637 else if (strcmp(args[myidx], "match") == 0) {
3638 myidx++;
3639 flags = STK_IS_MATCH;
3640 }
3641 else if (strcmp(args[myidx], "on") == 0) {
3642 myidx++;
3643 flags = STK_IS_MATCH | STK_IS_STORE;
3644 }
3645 else {
3646 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
3649 }
3650
3651 if (*(args[myidx]) == 0) {
3652 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3653 err_code |= ERR_ALERT | ERR_FATAL;
3654 goto out;
3655 }
3656
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003657 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003658 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003659 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003660 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003661 err_code |= ERR_ALERT | ERR_FATAL;
3662 goto out;
3663 }
3664
3665 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003666 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3667 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3668 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003669 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003670 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003671 goto out;
3672 }
3673 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003674 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3675 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3676 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003677 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003678 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003679 goto out;
3680 }
3681 }
3682
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003683 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003684 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003685
Emeric Brunb982a3d2010-01-04 15:45:53 +01003686 if (strcmp(args[myidx], "table") == 0) {
3687 myidx++;
3688 name = args[myidx++];
3689 }
3690
Willy Tarreauef6494c2010-01-28 17:12:36 +01003691 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003692 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3693 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3694 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003695 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003696 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003697 goto out;
3698 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003699 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003700 else if (*(args[myidx])) {
3701 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3702 file, linenum, args[0], args[myidx]);
3703 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003704 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003705 goto out;
3706 }
Emeric Brun97679e72010-09-23 17:56:44 +02003707 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003708 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003709 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003710 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003711
Emeric Brunb982a3d2010-01-04 15:45:53 +01003712 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3713 rule->cond = cond;
3714 rule->expr = expr;
3715 rule->flags = flags;
3716 rule->table.name = name ? strdup(name) : NULL;
3717 LIST_INIT(&rule->list);
3718 if (flags & STK_ON_RSP)
3719 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3720 else
3721 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3722 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003723 else if (!strcmp(args[0], "stats")) {
3724 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3725 curproxy->uri_auth = NULL; /* we must detach from the default config */
3726
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003727 if (!*args[1]) {
3728 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003729 } else if (!strcmp(args[1], "admin")) {
3730 struct stats_admin_rule *rule;
3731
3732 if (curproxy == &defproxy) {
3733 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3734 err_code |= ERR_ALERT | ERR_FATAL;
3735 goto out;
3736 }
3737
3738 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3739 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3740 err_code |= ERR_ALERT | ERR_ABORT;
3741 goto out;
3742 }
3743
3744 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3745 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3746 file, linenum, args[0], args[1]);
3747 err_code |= ERR_ALERT | ERR_FATAL;
3748 goto out;
3749 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003750 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3751 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3752 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003753 err_code |= ERR_ALERT | ERR_FATAL;
3754 goto out;
3755 }
3756
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003757 err_code |= warnif_cond_conflicts(cond,
3758 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3759 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003760
3761 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3762 rule->cond = cond;
3763 LIST_INIT(&rule->list);
3764 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003765 } else if (!strcmp(args[1], "uri")) {
3766 if (*(args[2]) == 0) {
3767 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003768 err_code |= ERR_ALERT | ERR_FATAL;
3769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003770 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3771 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003772 err_code |= ERR_ALERT | ERR_ABORT;
3773 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003774 }
3775 } else if (!strcmp(args[1], "realm")) {
3776 if (*(args[2]) == 0) {
3777 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003778 err_code |= ERR_ALERT | ERR_FATAL;
3779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003780 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3781 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003782 err_code |= ERR_ALERT | ERR_ABORT;
3783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003784 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003785 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003786 unsigned interval;
3787
3788 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3789 if (err) {
3790 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3791 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003794 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3795 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003796 err_code |= ERR_ALERT | ERR_ABORT;
3797 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003798 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003799 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003800 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003801
3802 if (curproxy == &defproxy) {
3803 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3804 err_code |= ERR_ALERT | ERR_FATAL;
3805 goto out;
3806 }
3807
3808 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3809 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3810 err_code |= ERR_ALERT | ERR_ABORT;
3811 goto out;
3812 }
3813
Willy Tarreauff011f22011-01-06 17:51:27 +01003814 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3815 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003816 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3817 file, linenum, args[0]);
3818 err_code |= ERR_WARN;
3819 }
3820
Willy Tarreauff011f22011-01-06 17:51:27 +01003821 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003822
Willy Tarreauff011f22011-01-06 17:51:27 +01003823 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003824 err_code |= ERR_ALERT | ERR_ABORT;
3825 goto out;
3826 }
3827
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003828 err_code |= warnif_cond_conflicts(rule->cond,
3829 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3830 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003831 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003832
Willy Tarreaubaaee002006-06-26 02:48:02 +02003833 } else if (!strcmp(args[1], "auth")) {
3834 if (*(args[2]) == 0) {
3835 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003836 err_code |= ERR_ALERT | ERR_FATAL;
3837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3839 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_ALERT | ERR_ABORT;
3841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003842 }
3843 } else if (!strcmp(args[1], "scope")) {
3844 if (*(args[2]) == 0) {
3845 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3849 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003850 err_code |= ERR_ALERT | ERR_ABORT;
3851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852 }
3853 } else if (!strcmp(args[1], "enable")) {
3854 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3855 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003856 err_code |= ERR_ALERT | ERR_ABORT;
3857 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003858 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003859 } else if (!strcmp(args[1], "hide-version")) {
3860 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3861 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003862 err_code |= ERR_ALERT | ERR_ABORT;
3863 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003864 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003865 } else if (!strcmp(args[1], "show-legends")) {
3866 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3867 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3868 err_code |= ERR_ALERT | ERR_ABORT;
3869 goto out;
3870 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003871 } else if (!strcmp(args[1], "show-node")) {
3872
3873 if (*args[2]) {
3874 int i;
3875 char c;
3876
3877 for (i=0; args[2][i]; i++) {
3878 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003879 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3880 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003881 break;
3882 }
3883
3884 if (!i || args[2][i]) {
3885 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3886 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3887 file, linenum, args[0], args[1]);
3888 err_code |= ERR_ALERT | ERR_FATAL;
3889 goto out;
3890 }
3891 }
3892
3893 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3894 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3895 err_code |= ERR_ALERT | ERR_ABORT;
3896 goto out;
3897 }
3898 } else if (!strcmp(args[1], "show-desc")) {
3899 char *desc = NULL;
3900
3901 if (*args[2]) {
3902 int i, len=0;
3903 char *d;
3904
Willy Tarreau348acfe2014-04-14 15:00:39 +02003905 for (i = 2; *args[i]; i++)
3906 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003907
3908 desc = d = (char *)calloc(1, len);
3909
Willy Tarreau348acfe2014-04-14 15:00:39 +02003910 d += snprintf(d, desc + len - d, "%s", args[2]);
3911 for (i = 3; *args[i]; i++)
3912 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003913 }
3914
3915 if (!*args[2] && !global.desc)
3916 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3917 file, linenum, args[1]);
3918 else {
3919 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3920 free(desc);
3921 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3922 err_code |= ERR_ALERT | ERR_ABORT;
3923 goto out;
3924 }
3925 free(desc);
3926 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003927 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003928stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003929 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 +01003930 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003931 err_code |= ERR_ALERT | ERR_FATAL;
3932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003933 }
3934 }
3935 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003936 int optnum;
3937
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003938 if (*(args[1]) == '\0') {
3939 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3940 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003941 err_code |= ERR_ALERT | ERR_FATAL;
3942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003943 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003944
3945 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3946 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003947 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3948 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3949 file, linenum, cfg_opts[optnum].name);
3950 err_code |= ERR_ALERT | ERR_FATAL;
3951 goto out;
3952 }
Willy Tarreau93893792009-07-23 13:19:11 +02003953 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3954 err_code |= ERR_WARN;
3955 goto out;
3956 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003957
Willy Tarreau3842f002009-06-14 11:39:52 +02003958 curproxy->no_options &= ~cfg_opts[optnum].val;
3959 curproxy->options &= ~cfg_opts[optnum].val;
3960
3961 switch (kwm) {
3962 case KWM_STD:
3963 curproxy->options |= cfg_opts[optnum].val;
3964 break;
3965 case KWM_NO:
3966 curproxy->no_options |= cfg_opts[optnum].val;
3967 break;
3968 case KWM_DEF: /* already cleared */
3969 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003970 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003971
Willy Tarreau93893792009-07-23 13:19:11 +02003972 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003973 }
3974 }
3975
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003976 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3977 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003978 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3979 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3980 file, linenum, cfg_opts2[optnum].name);
3981 err_code |= ERR_ALERT | ERR_FATAL;
3982 goto out;
3983 }
Willy Tarreau93893792009-07-23 13:19:11 +02003984 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3985 err_code |= ERR_WARN;
3986 goto out;
3987 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003988
Willy Tarreau3842f002009-06-14 11:39:52 +02003989 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3990 curproxy->options2 &= ~cfg_opts2[optnum].val;
3991
3992 switch (kwm) {
3993 case KWM_STD:
3994 curproxy->options2 |= cfg_opts2[optnum].val;
3995 break;
3996 case KWM_NO:
3997 curproxy->no_options2 |= cfg_opts2[optnum].val;
3998 break;
3999 case KWM_DEF: /* already cleared */
4000 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004001 }
Willy Tarreau93893792009-07-23 13:19:11 +02004002 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004003 }
4004 }
4005
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004006 /* HTTP options override each other. They can be cancelled using
4007 * "no option xxx" which only switches to default mode if the mode
4008 * was this one (useful for cancelling options set in defaults
4009 * sections).
4010 */
4011 if (strcmp(args[1], "httpclose") == 0) {
4012 if (kwm == KWM_STD) {
4013 curproxy->options &= ~PR_O_HTTP_MODE;
4014 curproxy->options |= PR_O_HTTP_PCL;
4015 goto out;
4016 }
4017 else if (kwm == KWM_NO) {
4018 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4019 curproxy->options &= ~PR_O_HTTP_MODE;
4020 goto out;
4021 }
4022 }
4023 else if (strcmp(args[1], "forceclose") == 0) {
4024 if (kwm == KWM_STD) {
4025 curproxy->options &= ~PR_O_HTTP_MODE;
4026 curproxy->options |= PR_O_HTTP_FCL;
4027 goto out;
4028 }
4029 else if (kwm == KWM_NO) {
4030 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4031 curproxy->options &= ~PR_O_HTTP_MODE;
4032 goto out;
4033 }
4034 }
4035 else if (strcmp(args[1], "http-server-close") == 0) {
4036 if (kwm == KWM_STD) {
4037 curproxy->options &= ~PR_O_HTTP_MODE;
4038 curproxy->options |= PR_O_HTTP_SCL;
4039 goto out;
4040 }
4041 else if (kwm == KWM_NO) {
4042 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4043 curproxy->options &= ~PR_O_HTTP_MODE;
4044 goto out;
4045 }
4046 }
4047 else if (strcmp(args[1], "http-keep-alive") == 0) {
4048 if (kwm == KWM_STD) {
4049 curproxy->options &= ~PR_O_HTTP_MODE;
4050 curproxy->options |= PR_O_HTTP_KAL;
4051 goto out;
4052 }
4053 else if (kwm == KWM_NO) {
4054 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4055 curproxy->options &= ~PR_O_HTTP_MODE;
4056 goto out;
4057 }
4058 }
4059 else if (strcmp(args[1], "http-tunnel") == 0) {
4060 if (kwm == KWM_STD) {
4061 curproxy->options &= ~PR_O_HTTP_MODE;
4062 curproxy->options |= PR_O_HTTP_TUN;
4063 goto out;
4064 }
4065 else if (kwm == KWM_NO) {
4066 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4067 curproxy->options &= ~PR_O_HTTP_MODE;
4068 goto out;
4069 }
4070 }
4071
Willy Tarreau3842f002009-06-14 11:39:52 +02004072 if (kwm != KWM_STD) {
4073 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004074 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004075 err_code |= ERR_ALERT | ERR_FATAL;
4076 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004077 }
4078
Emeric Brun3a058f32009-06-30 18:26:00 +02004079 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004080 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004081 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004082 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004083 if (*(args[2]) != '\0') {
4084 if (!strcmp(args[2], "clf")) {
4085 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004086 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004087 } else {
4088 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02004089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004091 }
4092 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004093 if (curproxy->conf.logformat_string != default_http_log_format &&
4094 curproxy->conf.logformat_string != default_tcp_log_format &&
4095 curproxy->conf.logformat_string != clf_http_log_format)
4096 free(curproxy->conf.logformat_string);
4097 curproxy->conf.logformat_string = logformat;
4098
4099 free(curproxy->conf.lfs_file);
4100 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4101 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004102 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004103 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004104 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004105 if (curproxy->conf.logformat_string != default_http_log_format &&
4106 curproxy->conf.logformat_string != default_tcp_log_format &&
4107 curproxy->conf.logformat_string != clf_http_log_format)
4108 free(curproxy->conf.logformat_string);
4109 curproxy->conf.logformat_string = default_tcp_log_format;
4110
4111 free(curproxy->conf.lfs_file);
4112 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4113 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004114 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004115 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004116 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004117 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004118 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004119
4120 if (curproxy->cap & PR_CAP_FE)
4121 curproxy->options |= PR_O_TCP_CLI_KA;
4122 if (curproxy->cap & PR_CAP_BE)
4123 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004124 }
4125 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004126 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004127 err_code |= ERR_WARN;
4128
Willy Tarreaubaaee002006-06-26 02:48:02 +02004129 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004130 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004131 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004132 curproxy->options2 &= ~PR_O2_CHK_ANY;
4133 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004134 if (!*args[2]) { /* no argument */
4135 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4136 curproxy->check_len = strlen(DEF_CHECK_REQ);
4137 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004138 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004139 curproxy->check_req = (char *)malloc(reqlen);
4140 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004141 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004142 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004143 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004144 if (*args[4])
4145 reqlen += strlen(args[4]);
4146 else
4147 reqlen += strlen("HTTP/1.0");
4148
4149 curproxy->check_req = (char *)malloc(reqlen);
4150 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004151 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004152 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004153 }
4154 else if (!strcmp(args[1], "ssl-hello-chk")) {
4155 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004156 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004157 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004158
Willy Tarreaua534fea2008-08-03 12:19:50 +02004159 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004160 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004161 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004162 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004163 }
Willy Tarreau23677902007-05-08 23:50:35 +02004164 else if (!strcmp(args[1], "smtpchk")) {
4165 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004166 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004167 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004168 curproxy->options2 &= ~PR_O2_CHK_ANY;
4169 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004170
4171 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4172 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4173 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4174 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4175 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4176 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4177 curproxy->check_req = (char *)malloc(reqlen);
4178 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4179 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4180 } else {
4181 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4182 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4183 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4184 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4185 }
4186 }
4187 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004188 else if (!strcmp(args[1], "pgsql-check")) {
4189 /* use PostgreSQL request to check servers' health */
4190 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4191 err_code |= ERR_WARN;
4192
4193 free(curproxy->check_req);
4194 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004195 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004196 curproxy->options2 |= PR_O2_PGSQL_CHK;
4197
4198 if (*(args[2])) {
4199 int cur_arg = 2;
4200
4201 while (*(args[cur_arg])) {
4202 if (strcmp(args[cur_arg], "user") == 0) {
4203 char * packet;
4204 uint32_t packet_len;
4205 uint32_t pv;
4206
4207 /* suboption header - needs additional argument for it */
4208 if (*(args[cur_arg+1]) == 0) {
4209 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4210 file, linenum, args[0], args[1], args[cur_arg]);
4211 err_code |= ERR_ALERT | ERR_FATAL;
4212 goto out;
4213 }
4214
4215 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4216 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4217 pv = htonl(0x30000); /* protocol version 3.0 */
4218
4219 packet = (char*) calloc(1, packet_len);
4220
4221 memcpy(packet + 4, &pv, 4);
4222
4223 /* copy "user" */
4224 memcpy(packet + 8, "user", 4);
4225
4226 /* copy username */
4227 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4228
4229 free(curproxy->check_req);
4230 curproxy->check_req = packet;
4231 curproxy->check_len = packet_len;
4232
4233 packet_len = htonl(packet_len);
4234 memcpy(packet, &packet_len, 4);
4235 cur_arg += 2;
4236 } else {
4237 /* unknown suboption - catchall */
4238 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4239 file, linenum, args[0], args[1]);
4240 err_code |= ERR_ALERT | ERR_FATAL;
4241 goto out;
4242 }
4243 } /* end while loop */
4244 }
4245 }
4246
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004247 else if (!strcmp(args[1], "redis-check")) {
4248 /* use REDIS PING request to check servers' health */
4249 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4250 err_code |= ERR_WARN;
4251
4252 free(curproxy->check_req);
4253 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004254 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004255 curproxy->options2 |= PR_O2_REDIS_CHK;
4256
4257 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4258 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4259 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4260 }
4261
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004262 else if (!strcmp(args[1], "mysql-check")) {
4263 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004264 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4265 err_code |= ERR_WARN;
4266
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004267 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004268 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004269 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004270 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004271
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004272 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004273 * const char mysql40_client_auth_pkt[] = {
4274 * "\x0e\x00\x00" // packet length
4275 * "\x01" // packet number
4276 * "\x00\x00" // client capabilities
4277 * "\x00\x00\x01" // max packet
4278 * "haproxy\x00" // username (null terminated string)
4279 * "\x00" // filler (always 0x00)
4280 * "\x01\x00\x00" // packet length
4281 * "\x00" // packet number
4282 * "\x01" // COM_QUIT command
4283 * };
4284 */
4285
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004286 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4287 * const char mysql41_client_auth_pkt[] = {
4288 * "\x0e\x00\x00\" // packet length
4289 * "\x01" // packet number
4290 * "\x00\x00\x00\x00" // client capabilities
4291 * "\x00\x00\x00\x01" // max packet
4292 * "\x21" // character set (UTF-8)
4293 * char[23] // All zeroes
4294 * "haproxy\x00" // username (null terminated string)
4295 * "\x00" // filler (always 0x00)
4296 * "\x01\x00\x00" // packet length
4297 * "\x00" // packet number
4298 * "\x01" // COM_QUIT command
4299 * };
4300 */
4301
4302
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004303 if (*(args[2])) {
4304 int cur_arg = 2;
4305
4306 while (*(args[cur_arg])) {
4307 if (strcmp(args[cur_arg], "user") == 0) {
4308 char *mysqluser;
4309 int packetlen, reqlen, userlen;
4310
4311 /* suboption header - needs additional argument for it */
4312 if (*(args[cur_arg+1]) == 0) {
4313 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4314 file, linenum, args[0], args[1], args[cur_arg]);
4315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
4317 }
4318 mysqluser = args[cur_arg + 1];
4319 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004320
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004321 if (*(args[cur_arg+2])) {
4322 if (!strcmp(args[cur_arg+2], "post-41")) {
4323 packetlen = userlen + 7 + 27;
4324 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004325
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004326 free(curproxy->check_req);
4327 curproxy->check_req = (char *)calloc(1, reqlen);
4328 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004329
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004330 snprintf(curproxy->check_req, 4, "%c%c%c",
4331 ((unsigned char) packetlen & 0xff),
4332 ((unsigned char) (packetlen >> 8) & 0xff),
4333 ((unsigned char) (packetlen >> 16) & 0xff));
4334
4335 curproxy->check_req[3] = 1;
4336 curproxy->check_req[5] = 130;
4337 curproxy->check_req[11] = 1;
4338 curproxy->check_req[12] = 33;
4339 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4340 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4341 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4342 cur_arg += 3;
4343 } else {
4344 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4345 err_code |= ERR_ALERT | ERR_FATAL;
4346 goto out;
4347 }
4348 } else {
4349 packetlen = userlen + 7;
4350 reqlen = packetlen + 9;
4351
4352 free(curproxy->check_req);
4353 curproxy->check_req = (char *)calloc(1, reqlen);
4354 curproxy->check_len = reqlen;
4355
4356 snprintf(curproxy->check_req, 4, "%c%c%c",
4357 ((unsigned char) packetlen & 0xff),
4358 ((unsigned char) (packetlen >> 8) & 0xff),
4359 ((unsigned char) (packetlen >> 16) & 0xff));
4360
4361 curproxy->check_req[3] = 1;
4362 curproxy->check_req[5] = 128;
4363 curproxy->check_req[8] = 1;
4364 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4365 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4366 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4367 cur_arg += 2;
4368 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004369 } else {
4370 /* unknown suboption - catchall */
4371 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4372 file, linenum, args[0], args[1]);
4373 err_code |= ERR_ALERT | ERR_FATAL;
4374 goto out;
4375 }
4376 } /* end while loop */
4377 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004378 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004379 else if (!strcmp(args[1], "ldap-check")) {
4380 /* use LDAP request to check servers' health */
4381 free(curproxy->check_req);
4382 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004383 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004384 curproxy->options2 |= PR_O2_LDAP_CHK;
4385
4386 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4387 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4388 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4389 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004390 else if (!strcmp(args[1], "tcp-check")) {
4391 /* use raw TCPCHK send/expect to check servers' health */
4392 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4393 err_code |= ERR_WARN;
4394
4395 free(curproxy->check_req);
4396 curproxy->check_req = NULL;
4397 curproxy->options2 &= ~PR_O2_CHK_ANY;
4398 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4399 }
Simon Horman98637e52014-06-20 12:30:16 +09004400 else if (!strcmp(args[1], "external-check")) {
4401 /* excute an external command to check servers' health */
4402 free(curproxy->check_req);
4403 curproxy->check_req = NULL;
4404 curproxy->options2 &= ~PR_O2_CHK_ANY;
4405 curproxy->options2 |= PR_O2_EXT_CHK;
4406 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004407 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004408 int cur_arg;
4409
4410 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4411 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004412 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004413
Willy Tarreau87cf5142011-08-19 22:57:24 +02004414 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004415
4416 free(curproxy->fwdfor_hdr_name);
4417 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4418 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4419
4420 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4421 cur_arg = 2;
4422 while (*(args[cur_arg])) {
4423 if (!strcmp(args[cur_arg], "except")) {
4424 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004425 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004426 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4427 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004428 err_code |= ERR_ALERT | ERR_FATAL;
4429 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004430 }
4431 /* flush useless bits */
4432 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004433 cur_arg += 2;
4434 } else if (!strcmp(args[cur_arg], "header")) {
4435 /* suboption header - needs additional argument for it */
4436 if (*(args[cur_arg+1]) == 0) {
4437 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4438 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004441 }
4442 free(curproxy->fwdfor_hdr_name);
4443 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4444 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4445 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004446 } else if (!strcmp(args[cur_arg], "if-none")) {
4447 curproxy->options &= ~PR_O_FF_ALWAYS;
4448 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004449 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004450 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004451 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004452 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004455 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004456 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004457 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004458 else if (!strcmp(args[1], "originalto")) {
4459 int cur_arg;
4460
4461 /* insert x-original-to field, but not for the IP address listed as an except.
4462 * set default options (ie: bitfield, header name, etc)
4463 */
4464
4465 curproxy->options |= PR_O_ORGTO;
4466
4467 free(curproxy->orgto_hdr_name);
4468 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4469 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4470
Willy Tarreau87cf5142011-08-19 22:57:24 +02004471 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004472 cur_arg = 2;
4473 while (*(args[cur_arg])) {
4474 if (!strcmp(args[cur_arg], "except")) {
4475 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004476 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 +02004477 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4478 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004479 err_code |= ERR_ALERT | ERR_FATAL;
4480 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004481 }
4482 /* flush useless bits */
4483 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4484 cur_arg += 2;
4485 } else if (!strcmp(args[cur_arg], "header")) {
4486 /* suboption header - needs additional argument for it */
4487 if (*(args[cur_arg+1]) == 0) {
4488 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4489 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004490 err_code |= ERR_ALERT | ERR_FATAL;
4491 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004492 }
4493 free(curproxy->orgto_hdr_name);
4494 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4495 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4496 cur_arg += 2;
4497 } else {
4498 /* unknown suboption - catchall */
4499 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4500 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004501 err_code |= ERR_ALERT | ERR_FATAL;
4502 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004503 }
4504 } /* end while loop */
4505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 else {
4507 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004508 err_code |= ERR_ALERT | ERR_FATAL;
4509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004510 }
Willy Tarreau93893792009-07-23 13:19:11 +02004511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004512 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004513 else if (!strcmp(args[0], "default_backend")) {
4514 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004515 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004516
4517 if (*(args[1]) == 0) {
4518 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004519 err_code |= ERR_ALERT | ERR_FATAL;
4520 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004521 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004522 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004523 curproxy->defbe.name = strdup(args[1]);
4524 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004525 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004526 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004527 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004528
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004529 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4530 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 +01004531 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004532 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004533 /* enable reconnections to dispatch */
4534 curproxy->options |= PR_O_REDISP;
4535 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004536 else if (!strcmp(args[0], "http-check")) {
4537 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004538 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004539
4540 if (strcmp(args[1], "disable-on-404") == 0) {
4541 /* enable a graceful server shutdown on an HTTP 404 response */
4542 curproxy->options |= PR_O_DISABLE404;
4543 }
Willy Tarreauef781042010-01-27 11:53:01 +01004544 else if (strcmp(args[1], "send-state") == 0) {
4545 /* enable emission of the apparent state of a server in HTTP checks */
4546 curproxy->options2 |= PR_O2_CHK_SNDST;
4547 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004548 else if (strcmp(args[1], "expect") == 0) {
4549 const char *ptr_arg;
4550 int cur_arg;
4551
4552 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4553 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4554 err_code |= ERR_ALERT | ERR_FATAL;
4555 goto out;
4556 }
4557
4558 cur_arg = 2;
4559 /* consider exclamation marks, sole or at the beginning of a word */
4560 while (*(ptr_arg = args[cur_arg])) {
4561 while (*ptr_arg == '!') {
4562 curproxy->options2 ^= PR_O2_EXP_INV;
4563 ptr_arg++;
4564 }
4565 if (*ptr_arg)
4566 break;
4567 cur_arg++;
4568 }
4569 /* now ptr_arg points to the beginning of a word past any possible
4570 * exclamation mark, and cur_arg is the argument which holds this word.
4571 */
4572 if (strcmp(ptr_arg, "status") == 0) {
4573 if (!*(args[cur_arg + 1])) {
4574 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4575 file, linenum, args[0], args[1], ptr_arg);
4576 err_code |= ERR_ALERT | ERR_FATAL;
4577 goto out;
4578 }
4579 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004580 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004581 curproxy->expect_str = strdup(args[cur_arg + 1]);
4582 }
4583 else if (strcmp(ptr_arg, "string") == 0) {
4584 if (!*(args[cur_arg + 1])) {
4585 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4586 file, linenum, args[0], args[1], ptr_arg);
4587 err_code |= ERR_ALERT | ERR_FATAL;
4588 goto out;
4589 }
4590 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004591 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004592 curproxy->expect_str = strdup(args[cur_arg + 1]);
4593 }
4594 else if (strcmp(ptr_arg, "rstatus") == 0) {
4595 if (!*(args[cur_arg + 1])) {
4596 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4597 file, linenum, args[0], args[1], ptr_arg);
4598 err_code |= ERR_ALERT | ERR_FATAL;
4599 goto out;
4600 }
4601 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004602 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004603 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004604 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004605 free(curproxy->expect_regex);
4606 curproxy->expect_regex = NULL;
4607 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004608 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004609 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4610 error = NULL;
4611 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4612 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4613 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4614 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004615 err_code |= ERR_ALERT | ERR_FATAL;
4616 goto out;
4617 }
4618 }
4619 else if (strcmp(ptr_arg, "rstring") == 0) {
4620 if (!*(args[cur_arg + 1])) {
4621 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4622 file, linenum, args[0], args[1], ptr_arg);
4623 err_code |= ERR_ALERT | ERR_FATAL;
4624 goto out;
4625 }
4626 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004627 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004628 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004629 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004630 free(curproxy->expect_regex);
4631 curproxy->expect_regex = NULL;
4632 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004633 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004634 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4635 error = NULL;
4636 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4637 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4638 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4639 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004640 err_code |= ERR_ALERT | ERR_FATAL;
4641 goto out;
4642 }
4643 }
4644 else {
4645 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4646 file, linenum, args[0], args[1], ptr_arg);
4647 err_code |= ERR_ALERT | ERR_FATAL;
4648 goto out;
4649 }
4650 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004651 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004652 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 +02004653 err_code |= ERR_ALERT | ERR_FATAL;
4654 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004655 }
4656 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004657 else if (!strcmp(args[0], "tcp-check")) {
4658 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4659 err_code |= ERR_WARN;
4660
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004661 if (strcmp(args[1], "connect") == 0) {
4662 const char *ptr_arg;
4663 int cur_arg;
4664 struct tcpcheck_rule *tcpcheck;
4665 struct list *l;
4666
4667 /* check if first rule is also a 'connect' action */
4668 l = (struct list *)&curproxy->tcpcheck_rules;
4669 if (l->p != l->n) {
4670 tcpcheck = (struct tcpcheck_rule *)l->n;
4671 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4672 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4673 file, linenum);
4674 err_code |= ERR_ALERT | ERR_FATAL;
4675 goto out;
4676 }
4677 }
4678
4679 cur_arg = 2;
4680 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4681 tcpcheck->action = TCPCHK_ACT_CONNECT;
4682
4683 /* parsing each parameters to fill up the rule */
4684 while (*(ptr_arg = args[cur_arg])) {
4685 /* tcp port */
4686 if (strcmp(args[cur_arg], "port") == 0) {
4687 if ( (atol(args[cur_arg + 1]) > 65535) ||
4688 (atol(args[cur_arg + 1]) < 1) ){
4689 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4690 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4691 err_code |= ERR_ALERT | ERR_FATAL;
4692 goto out;
4693 }
4694 tcpcheck->port = atol(args[cur_arg + 1]);
4695 cur_arg += 2;
4696 }
4697 /* send proxy protocol */
4698 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4699 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4700 cur_arg++;
4701 }
4702#ifdef USE_OPENSSL
4703 else if (strcmp(args[cur_arg], "ssl") == 0) {
4704 curproxy->options |= PR_O_TCPCHK_SSL;
4705 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4706 cur_arg++;
4707 }
4708#endif /* USE_OPENSSL */
4709 else {
4710#ifdef USE_OPENSSL
4711 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4712#else /* USE_OPENSSL */
4713 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4714#endif /* USE_OPENSSL */
4715 file, linenum, args[0], args[1], args[cur_arg]);
4716 err_code |= ERR_ALERT | ERR_FATAL;
4717 goto out;
4718 }
4719
4720 }
4721
4722 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4723 }
4724 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004725 if (! *(args[2]) ) {
4726 /* SEND string expected */
4727 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4728 file, linenum, args[0], args[1], args[2]);
4729 err_code |= ERR_ALERT | ERR_FATAL;
4730 goto out;
4731 } else {
4732 struct tcpcheck_rule *tcpcheck;
4733
4734 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4735
4736 tcpcheck->action = TCPCHK_ACT_SEND;
4737 tcpcheck->string_len = strlen(args[2]);
4738 tcpcheck->string = strdup(args[2]);
4739 tcpcheck->expect_regex = NULL;
4740
4741 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4742 }
4743 }
4744 else if (strcmp(args[1], "send-binary") == 0) {
4745 if (! *(args[2]) ) {
4746 /* SEND binary string expected */
4747 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4748 file, linenum, args[0], args[1], args[2]);
4749 err_code |= ERR_ALERT | ERR_FATAL;
4750 goto out;
4751 } else {
4752 struct tcpcheck_rule *tcpcheck;
4753 char *err = NULL;
4754
4755 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4756
4757 tcpcheck->action = TCPCHK_ACT_SEND;
4758 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4759 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4760 file, linenum, args[0], args[1], args[2], err);
4761 err_code |= ERR_ALERT | ERR_FATAL;
4762 goto out;
4763 }
4764 tcpcheck->expect_regex = NULL;
4765
4766 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4767 }
4768 }
4769 else if (strcmp(args[1], "expect") == 0) {
4770 const char *ptr_arg;
4771 int cur_arg;
4772 int inverse = 0;
4773
4774 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4775 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4776 err_code |= ERR_ALERT | ERR_FATAL;
4777 goto out;
4778 }
4779
4780 cur_arg = 2;
4781 /* consider exclamation marks, sole or at the beginning of a word */
4782 while (*(ptr_arg = args[cur_arg])) {
4783 while (*ptr_arg == '!') {
4784 inverse = !inverse;
4785 ptr_arg++;
4786 }
4787 if (*ptr_arg)
4788 break;
4789 cur_arg++;
4790 }
4791 /* now ptr_arg points to the beginning of a word past any possible
4792 * exclamation mark, and cur_arg is the argument which holds this word.
4793 */
4794 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004795 struct tcpcheck_rule *tcpcheck;
4796 char *err = NULL;
4797
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004798 if (!*(args[cur_arg + 1])) {
4799 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4800 file, linenum, args[0], args[1], ptr_arg);
4801 err_code |= ERR_ALERT | ERR_FATAL;
4802 goto out;
4803 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004804
4805 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4806
4807 tcpcheck->action = TCPCHK_ACT_EXPECT;
4808 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4809 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4810 file, linenum, args[0], args[1], args[2], err);
4811 err_code |= ERR_ALERT | ERR_FATAL;
4812 goto out;
4813 }
4814 tcpcheck->expect_regex = NULL;
4815 tcpcheck->inverse = inverse;
4816
4817 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4818 }
4819 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004820 struct tcpcheck_rule *tcpcheck;
4821
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004822 if (!*(args[cur_arg + 1])) {
4823 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4824 file, linenum, args[0], args[1], ptr_arg);
4825 err_code |= ERR_ALERT | ERR_FATAL;
4826 goto out;
4827 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004828
4829 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4830
4831 tcpcheck->action = TCPCHK_ACT_EXPECT;
4832 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4833 tcpcheck->string = strdup(args[cur_arg + 1]);
4834 tcpcheck->expect_regex = NULL;
4835 tcpcheck->inverse = inverse;
4836
4837 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4838 }
4839 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004840 struct tcpcheck_rule *tcpcheck;
4841
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004842 if (!*(args[cur_arg + 1])) {
4843 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4844 file, linenum, args[0], args[1], ptr_arg);
4845 err_code |= ERR_ALERT | ERR_FATAL;
4846 goto out;
4847 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004848
4849 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4850
4851 tcpcheck->action = TCPCHK_ACT_EXPECT;
4852 tcpcheck->string_len = 0;
4853 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004854 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4855 error = NULL;
4856 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4857 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4858 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4859 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
4862 }
4863 tcpcheck->inverse = inverse;
4864
4865 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4866 }
4867 else {
4868 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4869 file, linenum, args[0], args[1], ptr_arg);
4870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
4872 }
4873 }
4874 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004875 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004876 err_code |= ERR_ALERT | ERR_FATAL;
4877 goto out;
4878 }
4879 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004880 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004881 if (curproxy == &defproxy) {
4882 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004883 err_code |= ERR_ALERT | ERR_FATAL;
4884 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004885 }
4886
Willy Tarreaub80c2302007-11-30 20:51:32 +01004887 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004888 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004889
4890 if (strcmp(args[1], "fail") == 0) {
4891 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004892 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004893 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4894 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004895 err_code |= ERR_ALERT | ERR_FATAL;
4896 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004897 }
4898
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004899 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4900 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4901 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004902 err_code |= ERR_ALERT | ERR_FATAL;
4903 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004904 }
4905 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4906 }
4907 else {
4908 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004909 err_code |= ERR_ALERT | ERR_FATAL;
4910 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004911 }
4912 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004913#ifdef TPROXY
4914 else if (!strcmp(args[0], "transparent")) {
4915 /* enable transparent proxy connections */
4916 curproxy->options |= PR_O_TRANSP;
4917 }
4918#endif
4919 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004920 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004921 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004922
Willy Tarreaubaaee002006-06-26 02:48:02 +02004923 if (*(args[1]) == 0) {
4924 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004925 err_code |= ERR_ALERT | ERR_FATAL;
4926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004927 }
4928 curproxy->maxconn = atol(args[1]);
4929 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004930 else if (!strcmp(args[0], "backlog")) { /* backlog */
4931 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004932 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004933
4934 if (*(args[1]) == 0) {
4935 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004936 err_code |= ERR_ALERT | ERR_FATAL;
4937 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004938 }
4939 curproxy->backlog = atol(args[1]);
4940 }
Willy Tarreau86034312006-12-29 00:10:33 +01004941 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004942 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004943 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004944
Willy Tarreau86034312006-12-29 00:10:33 +01004945 if (*(args[1]) == 0) {
4946 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004947 err_code |= ERR_ALERT | ERR_FATAL;
4948 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004949 }
4950 curproxy->fullconn = atol(args[1]);
4951 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4953 if (*(args[1]) == 0) {
4954 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004955 err_code |= ERR_ALERT | ERR_FATAL;
4956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004957 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004958 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4959 if (err) {
4960 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4961 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004962 err_code |= ERR_ALERT | ERR_FATAL;
4963 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004964 }
4965 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004966 }
4967 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004968 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004969 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004970 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004971
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 if (curproxy == &defproxy) {
4973 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004974 err_code |= ERR_ALERT | ERR_FATAL;
4975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004976 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004977 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004978 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004979
Willy Tarreau902636f2013-03-10 19:44:48 +01004980 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004981 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004982 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004983 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004984 goto out;
4985 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004986
4987 proto = protocol_by_family(sk->ss_family);
4988 if (!proto || !proto->connect) {
4989 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4990 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004991 err_code |= ERR_ALERT | ERR_FATAL;
4992 goto out;
4993 }
4994
4995 if (port1 != port2) {
4996 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4997 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004998 err_code |= ERR_ALERT | ERR_FATAL;
4999 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005000 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005001
5002 if (!port1) {
5003 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5004 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005005 err_code |= ERR_ALERT | ERR_FATAL;
5006 goto out;
5007 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005008
Willy Tarreaud5191e72010-02-09 20:50:45 +01005009 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005010 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005011 }
5012 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005013 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005014 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005015
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005016 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5017 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005018 err_code |= ERR_ALERT | ERR_FATAL;
5019 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005020 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005021 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005022 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005023 /**
5024 * The syntax for hash-type config element is
5025 * hash-type {map-based|consistent} [[<algo>] avalanche]
5026 *
5027 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5028 */
5029 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005030
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005031 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5032 err_code |= ERR_WARN;
5033
5034 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005035 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5036 }
5037 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005038 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5039 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005040 else if (strcmp(args[1], "avalanche") == 0) {
5041 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]);
5042 err_code |= ERR_ALERT | ERR_FATAL;
5043 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005044 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005045 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005046 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005047 err_code |= ERR_ALERT | ERR_FATAL;
5048 goto out;
5049 }
Bhaskar98634f02013-10-29 23:30:51 -04005050
5051 /* set the hash function to use */
5052 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005053 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005054 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005055
5056 /* if consistent with no argument, then avalanche modifier is also applied */
5057 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5058 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005059 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005060 /* set the hash function */
5061 if (!strcmp(args[2], "sdbm")) {
5062 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5063 }
5064 else if (!strcmp(args[2], "djb2")) {
5065 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005066 }
5067 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005068 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005069 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005070 else if (!strcmp(args[2], "crc32")) {
5071 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5072 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005073 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005074 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 -05005075 err_code |= ERR_ALERT | ERR_FATAL;
5076 goto out;
5077 }
5078
5079 /* set the hash modifier */
5080 if (!strcmp(args[3], "avalanche")) {
5081 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5082 }
5083 else if (*args[3]) {
5084 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5085 err_code |= ERR_ALERT | ERR_FATAL;
5086 goto out;
5087 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005088 }
William Lallemanda73203e2012-03-12 12:48:57 +01005089 }
William Lallemanda73203e2012-03-12 12:48:57 +01005090 else if (strcmp(args[0], "unique-id-format") == 0) {
5091 if (!*(args[1])) {
5092 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5093 err_code |= ERR_ALERT | ERR_FATAL;
5094 goto out;
5095 }
William Lallemand3203ff42012-11-11 17:30:56 +01005096 if (*(args[2])) {
5097 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5098 err_code |= ERR_ALERT | ERR_FATAL;
5099 goto out;
5100 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005101 free(curproxy->conf.uniqueid_format_string);
5102 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005103
Willy Tarreau62a61232013-04-12 18:13:46 +02005104 free(curproxy->conf.uif_file);
5105 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5106 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005107 }
William Lallemanda73203e2012-03-12 12:48:57 +01005108
5109 else if (strcmp(args[0], "unique-id-header") == 0) {
5110 if (!*(args[1])) {
5111 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5112 err_code |= ERR_ALERT | ERR_FATAL;
5113 goto out;
5114 }
5115 free(curproxy->header_unique_id);
5116 curproxy->header_unique_id = strdup(args[1]);
5117 }
5118
William Lallemand723b73a2012-02-08 16:37:49 +01005119 else if (strcmp(args[0], "log-format") == 0) {
5120 if (!*(args[1])) {
5121 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5122 err_code |= ERR_ALERT | ERR_FATAL;
5123 goto out;
5124 }
William Lallemand3203ff42012-11-11 17:30:56 +01005125 if (*(args[2])) {
5126 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5127 err_code |= ERR_ALERT | ERR_FATAL;
5128 goto out;
5129 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005130
Willy Tarreau62a61232013-04-12 18:13:46 +02005131 if (curproxy->conf.logformat_string != default_http_log_format &&
5132 curproxy->conf.logformat_string != default_tcp_log_format &&
5133 curproxy->conf.logformat_string != clf_http_log_format)
5134 free(curproxy->conf.logformat_string);
5135 curproxy->conf.logformat_string = strdup(args[1]);
5136
5137 free(curproxy->conf.lfs_file);
5138 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5139 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005140
5141 /* get a chance to improve log-format error reporting by
5142 * reporting the correct line-number when possible.
5143 */
5144 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5145 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5146 file, linenum, curproxy->id);
5147 err_code |= ERR_WARN;
5148 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005149 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005150 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5151 if (*(args[1]) == 0) {
5152 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5153 err_code |= ERR_ALERT | ERR_FATAL;
5154 goto out;
5155 }
5156 free(curproxy->log_tag);
5157 curproxy->log_tag = strdup(args[1]);
5158 }
William Lallemand0f99e342011-10-12 17:50:54 +02005159 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5160 /* delete previous herited or defined syslog servers */
5161 struct logsrv *back;
5162
5163 if (*(args[1]) != 0) {
5164 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5165 err_code |= ERR_ALERT | ERR_FATAL;
5166 goto out;
5167 }
5168
William Lallemand723b73a2012-02-08 16:37:49 +01005169 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5170 LIST_DEL(&tmplogsrv->list);
5171 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005172 }
5173 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005174 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005175 struct logsrv *logsrv;
5176
Willy Tarreaubaaee002006-06-26 02:48:02 +02005177 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005178 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005179 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005180 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005181 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005182 LIST_INIT(&node->list);
5183 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5184 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005185 }
5186 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005187 struct sockaddr_storage *sk;
5188 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005189 int arg = 0;
5190 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005191
5192 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005193
Willy Tarreau18324f52014-06-27 18:10:07 +02005194 /* just after the address, a length may be specified */
5195 if (strcmp(args[arg+2], "len") == 0) {
5196 len = atoi(args[arg+3]);
5197 if (len < 80 || len > 65535) {
5198 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5199 file, linenum, args[arg+3]);
5200 err_code |= ERR_ALERT | ERR_FATAL;
5201 goto out;
5202 }
5203 logsrv->maxlen = len;
5204
5205 /* skip these two args */
5206 arg += 2;
5207 }
5208 else
5209 logsrv->maxlen = MAX_SYSLOG_LEN;
5210
5211 if (logsrv->maxlen > global.max_syslog_len) {
5212 global.max_syslog_len = logsrv->maxlen;
5213 logline = realloc(logline, global.max_syslog_len + 1);
5214 }
5215
5216 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005217 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005218 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005219 err_code |= ERR_ALERT | ERR_FATAL;
5220 goto out;
5221
Willy Tarreaubaaee002006-06-26 02:48:02 +02005222 }
5223
William Lallemand0f99e342011-10-12 17:50:54 +02005224 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005225 if (*(args[arg+3])) {
5226 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005227 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005228 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005229 err_code |= ERR_ALERT | ERR_FATAL;
5230 goto out;
5231
Willy Tarreaubaaee002006-06-26 02:48:02 +02005232 }
5233 }
5234
William Lallemand0f99e342011-10-12 17:50:54 +02005235 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005236 if (*(args[arg+4])) {
5237 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005238 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005239 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005240 err_code |= ERR_ALERT | ERR_FATAL;
5241 goto out;
5242
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005243 }
5244 }
5245
Willy Tarreau902636f2013-03-10 19:44:48 +01005246 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005247 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005248 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005249 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005250 goto out;
5251 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005252
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005253 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005254
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005255 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005256 if (port1 != port2) {
5257 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5258 file, linenum, args[0], args[1]);
5259 err_code |= ERR_ALERT | ERR_FATAL;
5260 goto out;
5261 }
5262
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005263 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005264 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005265 }
William Lallemand0f99e342011-10-12 17:50:54 +02005266
5267 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005268 }
5269 else {
5270 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5271 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005272 err_code |= ERR_ALERT | ERR_FATAL;
5273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005274 }
5275 }
5276 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005277 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005278 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005279 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005280 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005281
Willy Tarreau977b8e42006-12-29 14:19:17 +01005282 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005283 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005284
Willy Tarreaubaaee002006-06-26 02:48:02 +02005285 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005286 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5287 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005288 err_code |= ERR_ALERT | ERR_FATAL;
5289 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005290 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005291
5292 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005293 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5294 free(curproxy->conn_src.iface_name);
5295 curproxy->conn_src.iface_name = NULL;
5296 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005297
Willy Tarreau902636f2013-03-10 19:44:48 +01005298 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005299 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005300 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005301 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005302 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005303 goto out;
5304 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005305
5306 proto = protocol_by_family(sk->ss_family);
5307 if (!proto || !proto->connect) {
5308 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005309 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
5312 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005313
5314 if (port1 != port2) {
5315 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5316 file, linenum, args[0], args[1]);
5317 err_code |= ERR_ALERT | ERR_FATAL;
5318 goto out;
5319 }
5320
Willy Tarreauef9a3602012-12-08 22:29:20 +01005321 curproxy->conn_src.source_addr = *sk;
5322 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005323
5324 cur_arg = 2;
5325 while (*(args[cur_arg])) {
5326 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005327#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5328#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005329 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005330 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5331 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005332 err_code |= ERR_ALERT | ERR_FATAL;
5333 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005334 }
5335#endif
5336 if (!*args[cur_arg + 1]) {
5337 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5338 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005339 err_code |= ERR_ALERT | ERR_FATAL;
5340 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005341 }
5342
5343 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005344 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5345 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005346 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005347 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5348 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005349 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5350 char *name, *end;
5351
5352 name = args[cur_arg+1] + 7;
5353 while (isspace(*name))
5354 name++;
5355
5356 end = name;
5357 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5358 end++;
5359
Willy Tarreauef9a3602012-12-08 22:29:20 +01005360 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5361 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5362 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5363 curproxy->conn_src.bind_hdr_len = end - name;
5364 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5365 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5366 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005367
5368 /* now look for an occurrence number */
5369 while (isspace(*end))
5370 end++;
5371 if (*end == ',') {
5372 end++;
5373 name = end;
5374 if (*end == '-')
5375 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005376 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005377 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005378 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005379 }
5380
Willy Tarreauef9a3602012-12-08 22:29:20 +01005381 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005382 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5383 " occurrences values smaller than %d.\n",
5384 file, linenum, MAX_HDR_HISTORY);
5385 err_code |= ERR_ALERT | ERR_FATAL;
5386 goto out;
5387 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005388 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005389 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005390
Willy Tarreau902636f2013-03-10 19:44:48 +01005391 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005392 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005393 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005394 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005395 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005396 goto out;
5397 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005398
5399 proto = protocol_by_family(sk->ss_family);
5400 if (!proto || !proto->connect) {
5401 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5402 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005403 err_code |= ERR_ALERT | ERR_FATAL;
5404 goto out;
5405 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005406
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005407 if (port1 != port2) {
5408 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5409 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005410 err_code |= ERR_ALERT | ERR_FATAL;
5411 goto out;
5412 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005413 curproxy->conn_src.tproxy_addr = *sk;
5414 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005415 }
5416 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005417#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005418 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005419#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005420#else /* no TPROXY support */
5421 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005422 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005423 err_code |= ERR_ALERT | ERR_FATAL;
5424 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005425#endif
5426 cur_arg += 2;
5427 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005428 }
5429
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005430 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5431#ifdef SO_BINDTODEVICE
5432 if (!*args[cur_arg + 1]) {
5433 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5434 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005435 err_code |= ERR_ALERT | ERR_FATAL;
5436 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005437 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005438 free(curproxy->conn_src.iface_name);
5439 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5440 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005441 global.last_checks |= LSTCHK_NETADM;
5442#else
5443 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5444 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005445 err_code |= ERR_ALERT | ERR_FATAL;
5446 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005447#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005448 cur_arg += 2;
5449 continue;
5450 }
5451 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005452 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005453 err_code |= ERR_ALERT | ERR_FATAL;
5454 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005455 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005456 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005457 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5458 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5459 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005460 err_code |= ERR_ALERT | ERR_FATAL;
5461 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005462 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005463 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005464 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005465 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5466 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005467 err_code |= ERR_ALERT | ERR_FATAL;
5468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005469 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005470
5471 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005472 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005473 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005474 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005476 }
5477 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005478 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005479 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005480 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005481 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005483 }
5484 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005485 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005486 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005487 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005488 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005490 }
5491 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005492 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005493 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005494 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005495 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005497 }
5498 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005499 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005500 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005501 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005502 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005503 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005504 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005505 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005506 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005507 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005508 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005509 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005510 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005511 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005512 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005513 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005514 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005515 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005516 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005517 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005518
5519 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5520 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 +01005521 }
5522 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005523 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005524 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005525 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005526 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005527 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005528
5529 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5530 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 +01005531 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005532 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005533 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005534 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5535 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005536 err_code |= ERR_ALERT | ERR_FATAL;
5537 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005538 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005539
5540 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005541 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005542 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005543 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005545 }
5546 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005547 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005548 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005549 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005550 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005552 }
5553 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005554 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005555 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005556 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005557 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005559 }
5560 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005561 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005562 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005563 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005564 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005566 }
5567 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005568 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005569 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005570 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005571 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005573 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005574 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005575 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005576 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005577 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005578 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005579 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005580 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005581 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005582 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005583
Willy Tarreaubaaee002006-06-26 02:48:02 +02005584 if (curproxy == &defproxy) {
5585 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005586 err_code |= ERR_ALERT | ERR_FATAL;
5587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005588 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005589 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005590 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005591
Willy Tarreaubaaee002006-06-26 02:48:02 +02005592 if (*(args[1]) == 0) {
5593 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005594 err_code |= ERR_ALERT | ERR_FATAL;
5595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005596 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005597
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005598 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005599 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5600 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5601 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005602 err_code |= ERR_ALERT | ERR_FATAL;
5603 goto out;
5604 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005605 err_code |= warnif_cond_conflicts(cond,
5606 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5607 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005608 }
5609 else if (*args[2]) {
5610 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5611 file, linenum, args[0], args[2]);
5612 err_code |= ERR_ALERT | ERR_FATAL;
5613 goto out;
5614 }
5615
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005616 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005617 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005618 wl->s = strdup(args[1]);
5619 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005620 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005621 }
5622 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005623 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005624 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5625 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005626 err_code |= ERR_ALERT | ERR_FATAL;
5627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005628 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005629
Willy Tarreauade5ec42010-01-28 19:33:49 +01005630 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005631 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005632 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005633 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005635 }
5636 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005637 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005638 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005639 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005640 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005642 }
5643 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005644 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005645 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005646 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005647 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005649 }
5650 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005651 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005652 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5653 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005654 err_code |= ERR_ALERT | ERR_FATAL;
5655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005656 }
5657
Willy Tarreauade5ec42010-01-28 19:33:49 +01005658 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005659 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005660 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005661 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005662 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005663 }
5664 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005665 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005666 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005667 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005668 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005670 }
5671 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005672 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005673 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005674 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005675 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005677 }
5678 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005679 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005680
Willy Tarreaubaaee002006-06-26 02:48:02 +02005681 if (curproxy == &defproxy) {
5682 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005683 err_code |= ERR_ALERT | ERR_FATAL;
5684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005685 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005686 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005687 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005688
Willy Tarreaubaaee002006-06-26 02:48:02 +02005689 if (*(args[1]) == 0) {
5690 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005691 err_code |= ERR_ALERT | ERR_FATAL;
5692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005693 }
5694
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005695 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005696 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5697 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5698 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005699 err_code |= ERR_ALERT | ERR_FATAL;
5700 goto out;
5701 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005702 err_code |= warnif_cond_conflicts(cond,
5703 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5704 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005705 }
5706 else if (*args[2]) {
5707 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5708 file, linenum, args[0], args[2]);
5709 err_code |= ERR_ALERT | ERR_FATAL;
5710 goto out;
5711 }
5712
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005713 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005714 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005715 wl->s = strdup(args[1]);
5716 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005717 }
5718 else if (!strcmp(args[0], "errorloc") ||
5719 !strcmp(args[0], "errorloc302") ||
5720 !strcmp(args[0], "errorloc303")) { /* error location */
5721 int errnum, errlen;
5722 char *err;
5723
Willy Tarreau977b8e42006-12-29 14:19:17 +01005724 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005725 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005726
Willy Tarreaubaaee002006-06-26 02:48:02 +02005727 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005728 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005729 err_code |= ERR_ALERT | ERR_FATAL;
5730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005731 }
5732
5733 errnum = atol(args[1]);
5734 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005735 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5736 err = malloc(errlen);
5737 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005739 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5740 err = malloc(errlen);
5741 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005742 }
5743
Willy Tarreau0f772532006-12-23 20:51:41 +01005744 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5745 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005746 chunk_destroy(&curproxy->errmsg[rc]);
5747 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005748 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005749 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005750 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005751
5752 if (rc >= HTTP_ERR_SIZE) {
5753 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5754 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755 free(err);
5756 }
5757 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005758 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5759 int errnum, errlen, fd;
5760 char *err;
5761 struct stat stat;
5762
5763 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005764 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005765
5766 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005767 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005768 err_code |= ERR_ALERT | ERR_FATAL;
5769 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005770 }
5771
5772 fd = open(args[2], O_RDONLY);
5773 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5774 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5775 file, linenum, args[2], args[1]);
5776 if (fd >= 0)
5777 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005778 err_code |= ERR_ALERT | ERR_FATAL;
5779 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005780 }
5781
Willy Tarreau27a674e2009-08-17 07:23:33 +02005782 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005783 errlen = stat.st_size;
5784 } else {
5785 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005786 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005787 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005788 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005789 }
5790
5791 err = malloc(errlen); /* malloc() must succeed during parsing */
5792 errnum = read(fd, err, errlen);
5793 if (errnum != errlen) {
5794 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5795 file, linenum, args[2], args[1]);
5796 close(fd);
5797 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005798 err_code |= ERR_ALERT | ERR_FATAL;
5799 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005800 }
5801 close(fd);
5802
5803 errnum = atol(args[1]);
5804 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5805 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005806 chunk_destroy(&curproxy->errmsg[rc]);
5807 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005808 break;
5809 }
5810 }
5811
5812 if (rc >= HTTP_ERR_SIZE) {
5813 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5814 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005815 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005816 free(err);
5817 }
5818 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005819 else if (!strcmp(args[0], "compression")) {
5820 struct comp *comp;
5821 if (curproxy->comp == NULL) {
5822 comp = calloc(1, sizeof(struct comp));
5823 curproxy->comp = comp;
5824 } else {
5825 comp = curproxy->comp;
5826 }
5827
5828 if (!strcmp(args[1], "algo")) {
5829 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005830 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005831
William Lallemand82fe75c2012-10-23 10:25:10 +02005832 cur_arg = 2;
5833 if (!*args[cur_arg]) {
5834 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5835 file, linenum, args[0]);
5836 err_code |= ERR_ALERT | ERR_FATAL;
5837 goto out;
5838 }
5839 while (*(args[cur_arg])) {
5840 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5841 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5842 file, linenum, args[0], args[cur_arg]);
5843 err_code |= ERR_ALERT | ERR_FATAL;
5844 goto out;
5845 }
William Lallemand552df672012-11-07 13:21:47 +01005846 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5847 curproxy->comp->algos->end(&ctx);
5848 } else {
5849 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5850 file, linenum, args[0], args[cur_arg]);
5851 err_code |= ERR_ALERT | ERR_FATAL;
5852 goto out;
5853 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005854 cur_arg ++;
5855 continue;
5856 }
5857 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005858 else if (!strcmp(args[1], "offload")) {
5859 comp->offload = 1;
5860 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005861 else if (!strcmp(args[1], "type")) {
5862 int cur_arg;
5863 cur_arg = 2;
5864 if (!*args[cur_arg]) {
5865 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5866 file, linenum, args[0]);
5867 err_code |= ERR_ALERT | ERR_FATAL;
5868 goto out;
5869 }
5870 while (*(args[cur_arg])) {
5871 comp_append_type(comp, args[cur_arg]);
5872 cur_arg ++;
5873 continue;
5874 }
5875 }
5876 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005877 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005878 file, linenum, args[0]);
5879 err_code |= ERR_ALERT | ERR_FATAL;
5880 goto out;
5881 }
5882 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005883 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005884 struct cfg_kw_list *kwl;
5885 int index;
5886
5887 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5888 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5889 if (kwl->kw[index].section != CFG_LISTEN)
5890 continue;
5891 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5892 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005893 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005894 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005895 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005896 err_code |= ERR_ALERT | ERR_FATAL;
5897 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005898 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005899 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005900 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005901 err_code |= ERR_WARN;
5902 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005903 }
Willy Tarreau93893792009-07-23 13:19:11 +02005904 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005905 }
5906 }
5907 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005908
Willy Tarreau6daf3432008-01-22 16:44:08 +01005909 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005910 err_code |= ERR_ALERT | ERR_FATAL;
5911 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005912 }
Willy Tarreau93893792009-07-23 13:19:11 +02005913 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005914 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005915 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005916}
5917
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005918int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005919cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
5920{
5921#ifdef CONFIG_HAP_NS
5922 const char *err;
5923 const char *item = args[0];
5924
5925 if (!strcmp(item, "namespace_list")) {
5926 return 0;
5927 }
5928 else if (!strcmp(item, "namespace")) {
5929 size_t idx = 1;
5930 const char *current;
5931 while (*(current = args[idx++])) {
5932 err = invalid_char(current);
5933 if (err) {
5934 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5935 file, linenum, *err, item, current);
5936 return ERR_ALERT | ERR_FATAL;
5937 }
5938
5939 if (netns_store_lookup(current, strlen(current))) {
5940 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
5941 file, linenum, current);
5942 return ERR_ALERT | ERR_FATAL;
5943 }
5944 if (!netns_store_insert(current)) {
5945 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
5946 file, linenum, current);
5947 return ERR_ALERT | ERR_FATAL;
5948 }
5949 }
5950 }
5951
5952 return 0;
5953#else
5954 Alert("parsing [%s:%d]: namespace support is not compiled in.",
5955 file, linenum);
5956 return ERR_ALERT | ERR_FATAL;
5957#endif
5958}
5959
5960int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005961cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5962{
5963
5964 int err_code = 0;
5965 const char *err;
5966
5967 if (!strcmp(args[0], "userlist")) { /* new userlist */
5968 struct userlist *newul;
5969
5970 if (!*args[1]) {
5971 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5972 file, linenum, args[0]);
5973 err_code |= ERR_ALERT | ERR_FATAL;
5974 goto out;
5975 }
5976
5977 err = invalid_char(args[1]);
5978 if (err) {
5979 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5980 file, linenum, *err, args[0], args[1]);
5981 err_code |= ERR_ALERT | ERR_FATAL;
5982 goto out;
5983 }
5984
5985 for (newul = userlist; newul; newul = newul->next)
5986 if (!strcmp(newul->name, args[1])) {
5987 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5988 file, linenum, args[1]);
5989 err_code |= ERR_WARN;
5990 goto out;
5991 }
5992
5993 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5994 if (!newul) {
5995 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5996 err_code |= ERR_ALERT | ERR_ABORT;
5997 goto out;
5998 }
5999
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006000 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006001 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006002 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6003 err_code |= ERR_ALERT | ERR_ABORT;
6004 goto out;
6005 }
6006
6007 newul->next = userlist;
6008 userlist = newul;
6009
6010 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006011 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006012 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006013 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006014
6015 if (!*args[1]) {
6016 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6017 file, linenum, args[0]);
6018 err_code |= ERR_ALERT | ERR_FATAL;
6019 goto out;
6020 }
6021
6022 err = invalid_char(args[1]);
6023 if (err) {
6024 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6025 file, linenum, *err, args[0], args[1]);
6026 err_code |= ERR_ALERT | ERR_FATAL;
6027 goto out;
6028 }
6029
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006030 for (ag = userlist->groups; ag; ag = ag->next)
6031 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006032 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6033 file, linenum, args[1], userlist->name);
6034 err_code |= ERR_ALERT;
6035 goto out;
6036 }
6037
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006038 ag = calloc(1, sizeof(*ag));
6039 if (!ag) {
6040 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6041 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006042 goto out;
6043 }
6044
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006045 ag->name = strdup(args[1]);
6046 if (!ag) {
6047 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6048 err_code |= ERR_ALERT | ERR_ABORT;
6049 goto out;
6050 }
6051
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006052 cur_arg = 2;
6053
6054 while (*args[cur_arg]) {
6055 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006056 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006057 cur_arg += 2;
6058 continue;
6059 } else {
6060 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6061 file, linenum, args[0]);
6062 err_code |= ERR_ALERT | ERR_FATAL;
6063 goto out;
6064 }
6065 }
6066
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006067 ag->next = userlist->groups;
6068 userlist->groups = ag;
6069
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006070 } else if (!strcmp(args[0], "user")) { /* new user */
6071 struct auth_users *newuser;
6072 int cur_arg;
6073
6074 if (!*args[1]) {
6075 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6076 file, linenum, args[0]);
6077 err_code |= ERR_ALERT | ERR_FATAL;
6078 goto out;
6079 }
6080
6081 for (newuser = userlist->users; newuser; newuser = newuser->next)
6082 if (!strcmp(newuser->user, args[1])) {
6083 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6084 file, linenum, args[1], userlist->name);
6085 err_code |= ERR_ALERT;
6086 goto out;
6087 }
6088
6089 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6090 if (!newuser) {
6091 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6092 err_code |= ERR_ALERT | ERR_ABORT;
6093 goto out;
6094 }
6095
6096 newuser->user = strdup(args[1]);
6097
6098 newuser->next = userlist->users;
6099 userlist->users = newuser;
6100
6101 cur_arg = 2;
6102
6103 while (*args[cur_arg]) {
6104 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006105#ifdef CONFIG_HAP_CRYPT
6106 if (!crypt("", args[cur_arg + 1])) {
6107 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6108 file, linenum, newuser->user);
6109 err_code |= ERR_ALERT | ERR_FATAL;
6110 goto out;
6111 }
6112#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006113 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6114 file, linenum);
6115 err_code |= ERR_ALERT;
6116#endif
6117 newuser->pass = strdup(args[cur_arg + 1]);
6118 cur_arg += 2;
6119 continue;
6120 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6121 newuser->pass = strdup(args[cur_arg + 1]);
6122 newuser->flags |= AU_O_INSECURE;
6123 cur_arg += 2;
6124 continue;
6125 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006126 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006127 cur_arg += 2;
6128 continue;
6129 } else {
6130 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6131 file, linenum, args[0]);
6132 err_code |= ERR_ALERT | ERR_FATAL;
6133 goto out;
6134 }
6135 }
6136 } else {
6137 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6138 err_code |= ERR_ALERT | ERR_FATAL;
6139 }
6140
6141out:
6142 return err_code;
6143}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006144
6145/*
6146 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006147 * Returns the error code, 0 if OK, or any combination of :
6148 * - ERR_ABORT: must abort ASAP
6149 * - ERR_FATAL: we can continue parsing but not start the service
6150 * - ERR_WARN: a warning has been emitted
6151 * - ERR_ALERT: an alert has been emitted
6152 * Only the two first ones can stop processing, the two others are just
6153 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006154 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006155int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006156{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006157 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006158 FILE *f;
6159 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006160 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006161 struct cfg_section *cs = NULL;
6162 struct cfg_section *ics;
6163
6164 /* Register internal sections */
6165 if (!cfg_register_section("listen", cfg_parse_listen) ||
6166 !cfg_register_section("frontend", cfg_parse_listen) ||
6167 !cfg_register_section("backend", cfg_parse_listen) ||
6168 !cfg_register_section("ruleset", cfg_parse_listen) ||
6169 !cfg_register_section("defaults", cfg_parse_listen) ||
6170 !cfg_register_section("global", cfg_parse_global) ||
6171 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006172 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006173 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006174 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006175 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006176
Willy Tarreaubaaee002006-06-26 02:48:02 +02006177 if ((f=fopen(file,"r")) == NULL)
6178 return -1;
6179
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006180 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006181 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006182 char *end;
6183 char *args[MAX_LINE_ARGS + 1];
6184 char *line = thisline;
6185
Willy Tarreaubaaee002006-06-26 02:48:02 +02006186 linenum++;
6187
6188 end = line + strlen(line);
6189
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006190 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6191 /* Check if we reached the limit and the last char is not \n.
6192 * Watch out for the last line without the terminating '\n'!
6193 */
6194 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006195 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006196 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006197 }
6198
Willy Tarreaubaaee002006-06-26 02:48:02 +02006199 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006200 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006201 line++;
6202
6203 arg = 0;
6204 args[arg] = line;
6205
6206 while (*line && arg < MAX_LINE_ARGS) {
6207 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6208 * C equivalent value. Other combinations left unchanged (eg: \1).
6209 */
6210 if (*line == '\\') {
6211 int skip = 0;
6212 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6213 *line = line[1];
6214 skip = 1;
6215 }
6216 else if (line[1] == 'r') {
6217 *line = '\r';
6218 skip = 1;
6219 }
6220 else if (line[1] == 'n') {
6221 *line = '\n';
6222 skip = 1;
6223 }
6224 else if (line[1] == 't') {
6225 *line = '\t';
6226 skip = 1;
6227 }
6228 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006229 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006230 unsigned char hex1, hex2;
6231 hex1 = toupper(line[2]) - '0';
6232 hex2 = toupper(line[3]) - '0';
6233 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6234 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6235 *line = (hex1<<4) + hex2;
6236 skip = 3;
6237 }
6238 else {
6239 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006240 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006241 }
6242 }
6243 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006244 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006245 end -= skip;
6246 }
6247 line++;
6248 }
6249 else if (*line == '#' || *line == '\n' || *line == '\r') {
6250 /* end of string, end of loop */
6251 *line = 0;
6252 break;
6253 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006254 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006255 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006256 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006257 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006258 line++;
6259 args[++arg] = line;
6260 }
6261 else {
6262 line++;
6263 }
6264 }
6265
6266 /* empty line */
6267 if (!**args)
6268 continue;
6269
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006270 if (*line) {
6271 /* we had to stop due to too many args.
6272 * Let's terminate the string, print the offending part then cut the
6273 * last arg.
6274 */
6275 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6276 line++;
6277 *line = '\0';
6278
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006279 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006280 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006281 err_code |= ERR_ALERT | ERR_FATAL;
6282 args[arg] = line;
6283 }
6284
Willy Tarreau540abe42007-05-02 20:50:16 +02006285 /* zero out remaining args and ensure that at least one entry
6286 * is zeroed out.
6287 */
6288 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006289 args[arg] = line;
6290 }
6291
Willy Tarreau3842f002009-06-14 11:39:52 +02006292 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006293 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006294 char *tmp;
6295
Willy Tarreau3842f002009-06-14 11:39:52 +02006296 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006297 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006298 for (arg=0; *args[arg+1]; arg++)
6299 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006300 *tmp = '\0'; // fix the next arg to \0
6301 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006302 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006303 else if (!strcmp(args[0], "default")) {
6304 kwm = KWM_DEF;
6305 for (arg=0; *args[arg+1]; arg++)
6306 args[arg] = args[arg+1]; // shift args after inversion
6307 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006308
William Lallemand0f99e342011-10-12 17:50:54 +02006309 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6310 strcmp(args[0], "log") != 0) {
6311 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006312 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006313 }
6314
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006315 /* detect section start */
6316 list_for_each_entry(ics, &sections, list) {
6317 if (strcmp(args[0], ics->section_name) == 0) {
6318 cursection = ics->section_name;
6319 cs = ics;
6320 break;
6321 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006322 }
6323
Willy Tarreaubaaee002006-06-26 02:48:02 +02006324 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006325 if (cs)
6326 err_code |= cs->section_parser(file, linenum, args, kwm);
6327 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006328 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006329 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006330 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006331
6332 if (err_code & ERR_ABORT)
6333 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006334 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006335 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006336 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006337 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006338}
6339
Willy Tarreau64ab6072014-09-16 12:17:36 +02006340/* This function propagates processes from frontend <from> to backend <to> so
6341 * that it is always guaranteed that a backend pointed to by a frontend is
6342 * bound to all of its processes. After that, if the target is a "listen"
6343 * instance, the function recursively descends the target's own targets along
6344 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6345 * checked first to ensure that <to> is already bound to all processes of
6346 * <from>, there is no risk of looping and we ensure to follow the shortest
6347 * path to the destination.
6348 *
6349 * It is possible to set <to> to NULL for the first call so that the function
6350 * takes care of visiting the initial frontend in <from>.
6351 *
6352 * It is important to note that the function relies on the fact that all names
6353 * have already been resolved.
6354 */
6355void propagate_processes(struct proxy *from, struct proxy *to)
6356{
6357 struct switching_rule *rule;
6358 struct hdr_exp *exp;
6359
6360 if (to) {
6361 /* check whether we need to go down */
6362 if (from->bind_proc &&
6363 (from->bind_proc & to->bind_proc) == from->bind_proc)
6364 return;
6365
6366 if (!from->bind_proc && !to->bind_proc)
6367 return;
6368
6369 to->bind_proc = from->bind_proc ?
6370 (to->bind_proc | from->bind_proc) : 0;
6371
6372 /* now propagate down */
6373 from = to;
6374 }
6375
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006376 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006377 return;
6378
Willy Tarreauf6b70012014-12-18 14:00:43 +01006379 if (from->state == PR_STSTOPPED)
6380 return;
6381
Willy Tarreau64ab6072014-09-16 12:17:36 +02006382 /* default_backend */
6383 if (from->defbe.be)
6384 propagate_processes(from, from->defbe.be);
6385
6386 /* use_backend */
6387 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006388 if (rule->dynamic)
6389 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006390 to = rule->be.backend;
6391 propagate_processes(from, to);
6392 }
6393
6394 /* reqsetbe */
6395 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6396 if (exp->action != ACT_SETBE)
6397 continue;
6398 to = (struct proxy *)exp->replace;
6399 propagate_processes(from, to);
6400 }
6401}
6402
Willy Tarreaubb925012009-07-23 13:36:36 +02006403/*
6404 * Returns the error code, 0 if OK, or any combination of :
6405 * - ERR_ABORT: must abort ASAP
6406 * - ERR_FATAL: we can continue parsing but not start the service
6407 * - ERR_WARN: a warning has been emitted
6408 * - ERR_ALERT: an alert has been emitted
6409 * Only the two first ones can stop processing, the two others are just
6410 * indicators.
6411 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006412int check_config_validity()
6413{
6414 int cfgerr = 0;
6415 struct proxy *curproxy = NULL;
6416 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006417 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006418 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006419 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006420
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006421 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006422 /*
6423 * Now, check for the integrity of all that we have collected.
6424 */
6425
6426 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006427 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006428
Willy Tarreau193b8c62012-11-22 00:17:38 +01006429 if (!global.tune.max_http_hdr)
6430 global.tune.max_http_hdr = MAX_HTTP_HDR;
6431
6432 if (!global.tune.cookie_len)
6433 global.tune.cookie_len = CAPTURE_LEN;
6434
6435 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6436
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006437 /* Post initialisation of the users and groups lists. */
6438 err_code = userlist_postinit();
6439 if (err_code != ERR_NONE)
6440 goto out;
6441
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006442 /* first, we will invert the proxy list order */
6443 curproxy = NULL;
6444 while (proxy) {
6445 struct proxy *next;
6446
6447 next = proxy->next;
6448 proxy->next = curproxy;
6449 curproxy = proxy;
6450 if (!next)
6451 break;
6452 proxy = next;
6453 }
6454
Willy Tarreau419ead82014-09-16 13:41:21 +02006455 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006456 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006457 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006458 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006459 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006460 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006461 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006462 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006463
Willy Tarreau050536d2012-10-04 08:47:34 +02006464 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006465 /* proxy ID not set, use automatic numbering with first
6466 * spare entry starting with next_pxid.
6467 */
6468 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6469 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6470 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006471 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006472 next_pxid++;
6473
Willy Tarreau55ea7572007-06-17 19:56:27 +02006474
Willy Tarreaubaaee002006-06-26 02:48:02 +02006475 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006476 /* ensure we don't keep listeners uselessly bound */
6477 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006478 continue;
6479 }
6480
Willy Tarreau102df612014-05-07 23:56:38 +02006481 /* Check multi-process mode compatibility for the current proxy */
6482
6483 if (curproxy->bind_proc) {
6484 /* an explicit bind-process was specified, let's check how many
6485 * processes remain.
6486 */
6487 nbproc = popcount(curproxy->bind_proc);
6488
6489 curproxy->bind_proc &= nbits(global.nbproc);
6490 if (!curproxy->bind_proc && nbproc == 1) {
6491 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);
6492 curproxy->bind_proc = 1;
6493 }
6494 else if (!curproxy->bind_proc && nbproc > 1) {
6495 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);
6496 curproxy->bind_proc = 0;
6497 }
6498 }
6499
Willy Tarreau3d209582014-05-09 17:06:11 +02006500 /* check and reduce the bind-proc of each listener */
6501 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6502 unsigned long mask;
6503
6504 if (!bind_conf->bind_proc)
6505 continue;
6506
6507 mask = nbits(global.nbproc);
6508 if (curproxy->bind_proc)
6509 mask &= curproxy->bind_proc;
6510 /* mask cannot be null here thanks to the previous checks */
6511
6512 nbproc = popcount(bind_conf->bind_proc);
6513 bind_conf->bind_proc &= mask;
6514
6515 if (!bind_conf->bind_proc && nbproc == 1) {
6516 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",
6517 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6518 bind_conf->bind_proc = mask & ~(mask - 1);
6519 }
6520 else if (!bind_conf->bind_proc && nbproc > 1) {
6521 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",
6522 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6523 bind_conf->bind_proc = 0;
6524 }
6525 }
6526
Willy Tarreau102df612014-05-07 23:56:38 +02006527 if (global.nbproc > 1 && curproxy->table.peers.name) {
6528 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6529 curproxy->id);
6530 cfgerr++;
6531 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006532
Willy Tarreauff01a212009-03-15 13:46:16 +01006533 switch (curproxy->mode) {
6534 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006535 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006536 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006537 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6538 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006539 cfgerr++;
6540 }
6541
6542 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006543 Warning("config : servers will be ignored for %s '%s'.\n",
6544 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006545 break;
6546
6547 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006548 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006549 break;
6550
6551 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006552 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006553 break;
6554 }
6555
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006556 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006557 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006558 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006559 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6560 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006561 cfgerr++;
6562 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006563#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006564 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006565 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6566 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006567 cfgerr++;
6568 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006569#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006570 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006571 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6572 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006573 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006574 }
6575 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006576 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006577 /* If no LB algo is set in a backend, and we're not in
6578 * transparent mode, dispatch mode nor proxy mode, we
6579 * want to use balance roundrobin by default.
6580 */
6581 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6582 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006583 }
6584 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006585
Willy Tarreau1620ec32011-08-06 17:05:02 +02006586 if (curproxy->options & PR_O_DISPATCH)
6587 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6588 else if (curproxy->options & PR_O_HTTP_PROXY)
6589 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6590 else if (curproxy->options & PR_O_TRANSP)
6591 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006592
Willy Tarreau1620ec32011-08-06 17:05:02 +02006593 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6594 if (curproxy->options & PR_O_DISABLE404) {
6595 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6596 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6597 err_code |= ERR_WARN;
6598 curproxy->options &= ~PR_O_DISABLE404;
6599 }
6600 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6601 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6602 "send-state", proxy_type_str(curproxy), curproxy->id);
6603 err_code |= ERR_WARN;
6604 curproxy->options &= ~PR_O2_CHK_SNDST;
6605 }
Willy Tarreauef781042010-01-27 11:53:01 +01006606 }
6607
Simon Horman98637e52014-06-20 12:30:16 +09006608 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6609 if (!global.external_check) {
6610 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6611 curproxy->id, "option external-check");
6612 cfgerr++;
6613 }
6614 if (!curproxy->check_command) {
6615 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6616 curproxy->id, "option external-check");
6617 cfgerr++;
6618 }
6619 }
6620
Simon Horman64e34162015-02-06 11:11:57 +09006621 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006622 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
6623 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09006624 "'email-alert from', 'email-alert level' 'email-alert mailer', "
6625 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006626 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
6627 "to be present).\n",
6628 proxy_type_str(curproxy), curproxy->id);
6629 err_code |= ERR_WARN;
6630 free_email_alert(curproxy);
6631 }
6632 if (!curproxy->email_alert.myhostname)
6633 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09006634 }
6635
Simon Horman98637e52014-06-20 12:30:16 +09006636 if (curproxy->check_command) {
6637 int clear = 0;
6638 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6639 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6640 "external-check command", proxy_type_str(curproxy), curproxy->id);
6641 err_code |= ERR_WARN;
6642 clear = 1;
6643 }
6644 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6645 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6646 curproxy->id, "external-check command");
6647 cfgerr++;
6648 }
6649 if (clear) {
6650 free(curproxy->check_command);
6651 curproxy->check_command = NULL;
6652 }
6653 }
6654
6655 if (curproxy->check_path) {
6656 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6657 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6658 "external-check path", proxy_type_str(curproxy), curproxy->id);
6659 err_code |= ERR_WARN;
6660 free(curproxy->check_path);
6661 curproxy->check_path = NULL;
6662 }
6663 }
6664
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006665 /* if a default backend was specified, let's find it */
6666 if (curproxy->defbe.name) {
6667 struct proxy *target;
6668
Alex Williams96532db2009-11-01 21:27:13 -05006669 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006670 if (!target) {
6671 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6672 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006673 cfgerr++;
6674 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006675 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6676 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006677 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006678 } else {
6679 free(curproxy->defbe.name);
6680 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006681
6682 /* Emit a warning if this proxy also has some servers */
6683 if (curproxy->srv) {
6684 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6685 curproxy->id);
6686 err_code |= ERR_WARN;
6687 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006688 }
6689 }
6690
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006691 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006692 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6693 /* map jump target for ACT_SETBE in req_rep chain */
6694 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006695 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006696 struct proxy *target;
6697
Willy Tarreaua496b602006-12-17 23:15:24 +01006698 if (exp->action != ACT_SETBE)
6699 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006700
Alex Williams96532db2009-11-01 21:27:13 -05006701 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006702 if (!target) {
6703 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6704 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006705 cfgerr++;
6706 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006707 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6708 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006709 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006710 } else {
6711 free((void *)exp->replace);
6712 exp->replace = (const char *)target;
6713 }
6714 }
6715 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006716
6717 /* find the target proxy for 'use_backend' rules */
6718 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006719 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006720 struct logformat_node *node;
6721 char *pxname;
6722
6723 /* Try to parse the string as a log format expression. If the result
6724 * of the parsing is only one entry containing a simple string, then
6725 * it's a standard string corresponding to a static rule, thus the
6726 * parsing is cancelled and be.name is restored to be resolved.
6727 */
6728 pxname = rule->be.name;
6729 LIST_INIT(&rule->be.expr);
6730 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6731 curproxy->conf.args.file, curproxy->conf.args.line);
6732 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6733
6734 if (!LIST_ISEMPTY(&rule->be.expr)) {
6735 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6736 rule->dynamic = 1;
6737 free(pxname);
6738 continue;
6739 }
6740 /* simple string: free the expression and fall back to static rule */
6741 free(node->arg);
6742 free(node);
6743 }
6744
6745 rule->dynamic = 0;
6746 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006747
Alex Williams96532db2009-11-01 21:27:13 -05006748 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006749
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006750 if (!target) {
6751 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6752 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006753 cfgerr++;
6754 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006755 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6756 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006757 cfgerr++;
6758 } else {
6759 free((void *)rule->be.name);
6760 rule->be.backend = target;
6761 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006762 }
6763
Willy Tarreau64ab6072014-09-16 12:17:36 +02006764 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006765 list_for_each_entry(srule, &curproxy->server_rules, list) {
6766 struct server *target = findserver(curproxy, srule->srv.name);
6767
6768 if (!target) {
6769 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6770 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6771 cfgerr++;
6772 continue;
6773 }
6774 free((void *)srule->srv.name);
6775 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006776 }
6777
Emeric Brunb982a3d2010-01-04 15:45:53 +01006778 /* find the target table for 'stick' rules */
6779 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6780 struct proxy *target;
6781
Emeric Brun1d33b292010-01-04 15:47:17 +01006782 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6783 if (mrule->flags & STK_IS_STORE)
6784 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6785
Emeric Brunb982a3d2010-01-04 15:45:53 +01006786 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006787 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006788 else
6789 target = curproxy;
6790
6791 if (!target) {
6792 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6793 curproxy->id, mrule->table.name);
6794 cfgerr++;
6795 }
6796 else if (target->table.size == 0) {
6797 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6798 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6799 cfgerr++;
6800 }
Willy Tarreau12785782012-04-27 21:37:17 +02006801 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6802 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006803 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6804 cfgerr++;
6805 }
6806 else {
6807 free((void *)mrule->table.name);
6808 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006809 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006810 }
6811 }
6812
6813 /* find the target table for 'store response' rules */
6814 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6815 struct proxy *target;
6816
Emeric Brun1d33b292010-01-04 15:47:17 +01006817 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6818
Emeric Brunb982a3d2010-01-04 15:45:53 +01006819 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006820 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006821 else
6822 target = curproxy;
6823
6824 if (!target) {
6825 Alert("Proxy '%s': unable to find store table '%s'.\n",
6826 curproxy->id, mrule->table.name);
6827 cfgerr++;
6828 }
6829 else if (target->table.size == 0) {
6830 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6831 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6832 cfgerr++;
6833 }
Willy Tarreau12785782012-04-27 21:37:17 +02006834 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6835 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006836 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6837 cfgerr++;
6838 }
6839 else {
6840 free((void *)mrule->table.name);
6841 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006842 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006843 }
6844 }
6845
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006846 /* find the target table for 'tcp-request' layer 4 rules */
6847 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6848 struct proxy *target;
6849
Willy Tarreaub4c84932013-07-23 19:15:30 +02006850 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006851 continue;
6852
6853 if (trule->act_prm.trk_ctr.table.n)
6854 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6855 else
6856 target = curproxy;
6857
6858 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006859 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6860 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006861 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006862 cfgerr++;
6863 }
6864 else if (target->table.size == 0) {
6865 Alert("Proxy '%s': table '%s' used but not configured.\n",
6866 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6867 cfgerr++;
6868 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006869 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6870 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6871 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 +01006872 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006873 cfgerr++;
6874 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006875 else {
6876 free(trule->act_prm.trk_ctr.table.n);
6877 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006878 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006879 * to pass a list of counters to track and allocate them right here using
6880 * stktable_alloc_data_type().
6881 */
6882 }
6883 }
6884
Willy Tarreaud1f96522010-08-03 19:34:32 +02006885 /* find the target table for 'tcp-request' layer 6 rules */
6886 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6887 struct proxy *target;
6888
Willy Tarreaub4c84932013-07-23 19:15:30 +02006889 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006890 continue;
6891
6892 if (trule->act_prm.trk_ctr.table.n)
6893 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6894 else
6895 target = curproxy;
6896
6897 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006898 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6899 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006900 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006901 cfgerr++;
6902 }
6903 else if (target->table.size == 0) {
6904 Alert("Proxy '%s': table '%s' used but not configured.\n",
6905 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6906 cfgerr++;
6907 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006908 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6909 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6910 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 +01006911 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006912 cfgerr++;
6913 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006914 else {
6915 free(trule->act_prm.trk_ctr.table.n);
6916 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006917 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006918 * to pass a list of counters to track and allocate them right here using
6919 * stktable_alloc_data_type().
6920 */
6921 }
6922 }
6923
Willy Tarreau09448f72014-06-25 18:12:15 +02006924 /* find the target table for 'http-request' layer 7 rules */
6925 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6926 struct proxy *target;
6927
6928 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6929 continue;
6930
6931 if (hrqrule->act_prm.trk_ctr.table.n)
6932 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6933 else
6934 target = curproxy;
6935
6936 if (!target) {
6937 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6938 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6939 http_req_trk_idx(hrqrule->action));
6940 cfgerr++;
6941 }
6942 else if (target->table.size == 0) {
6943 Alert("Proxy '%s': table '%s' used but not configured.\n",
6944 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6945 cfgerr++;
6946 }
6947 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6948 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6949 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6950 http_req_trk_idx(hrqrule->action));
6951 cfgerr++;
6952 }
6953 else {
6954 free(hrqrule->act_prm.trk_ctr.table.n);
6955 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6956 /* Note: if we decide to enhance the track-sc syntax, we may be able
6957 * to pass a list of counters to track and allocate them right here using
6958 * stktable_alloc_data_type().
6959 */
6960 }
6961 }
6962
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006963 /* move any "block" rules at the beginning of the http-request rules */
6964 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6965 /* insert block_rules into http_req_rules at the beginning */
6966 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6967 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6968 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6969 curproxy->http_req_rules.n = curproxy->block_rules.n;
6970 LIST_INIT(&curproxy->block_rules);
6971 }
6972
Emeric Brun32da3c42010-09-23 18:39:19 +02006973 if (curproxy->table.peers.name) {
6974 struct peers *curpeers = peers;
6975
6976 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6977 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6978 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006979 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006980 break;
6981 }
6982 }
6983
6984 if (!curpeers) {
6985 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6986 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006987 free((void *)curproxy->table.peers.name);
6988 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006989 cfgerr++;
6990 }
6991 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006992 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6993 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006994 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006995 cfgerr++;
6996 }
6997 }
6998
Simon Horman9dc49962015-01-30 11:22:59 +09006999
7000 if (curproxy->email_alert.mailers.name) {
7001 struct mailers *curmailers = mailers;
7002
7003 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7004 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7005 free(curproxy->email_alert.mailers.name);
7006 curproxy->email_alert.mailers.m = curmailers;
7007 curmailers->users++;
7008 break;
7009 }
7010 }
7011
7012 if (!curmailers) {
7013 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7014 curproxy->id, curproxy->email_alert.mailers.name);
7015 free_email_alert(curproxy);
7016 cfgerr++;
7017 }
7018 }
7019
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007020 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007021 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007022 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7023 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7024 "proxy", curproxy->id);
7025 cfgerr++;
7026 goto out_uri_auth_compat;
7027 }
7028
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007029 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007030 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007031 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007032 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007033
Willy Tarreau95fa4692010-02-01 13:05:50 +01007034 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7035 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007036
7037 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007038 uri_auth_compat_req[i++] = "realm";
7039 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7040 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007041
Willy Tarreau95fa4692010-02-01 13:05:50 +01007042 uri_auth_compat_req[i++] = "unless";
7043 uri_auth_compat_req[i++] = "{";
7044 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7045 uri_auth_compat_req[i++] = "}";
7046 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007047
Willy Tarreauff011f22011-01-06 17:51:27 +01007048 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7049 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007050 cfgerr++;
7051 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007052 }
7053
Willy Tarreauff011f22011-01-06 17:51:27 +01007054 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007055
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007056 if (curproxy->uri_auth->auth_realm) {
7057 free(curproxy->uri_auth->auth_realm);
7058 curproxy->uri_auth->auth_realm = NULL;
7059 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007060
7061 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007062 }
7063out_uri_auth_compat:
7064
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007065 /* compile the log format */
7066 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007067 if (curproxy->conf.logformat_string != default_http_log_format &&
7068 curproxy->conf.logformat_string != default_tcp_log_format &&
7069 curproxy->conf.logformat_string != clf_http_log_format)
7070 free(curproxy->conf.logformat_string);
7071 curproxy->conf.logformat_string = NULL;
7072 free(curproxy->conf.lfs_file);
7073 curproxy->conf.lfs_file = NULL;
7074 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007075 }
7076
Willy Tarreau62a61232013-04-12 18:13:46 +02007077 if (curproxy->conf.logformat_string) {
7078 curproxy->conf.args.ctx = ARGC_LOG;
7079 curproxy->conf.args.file = curproxy->conf.lfs_file;
7080 curproxy->conf.args.line = curproxy->conf.lfs_line;
7081 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007082 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007083 curproxy->conf.args.file = NULL;
7084 curproxy->conf.args.line = 0;
7085 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007086
Willy Tarreau62a61232013-04-12 18:13:46 +02007087 if (curproxy->conf.uniqueid_format_string) {
7088 curproxy->conf.args.ctx = ARGC_UIF;
7089 curproxy->conf.args.file = curproxy->conf.uif_file;
7090 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007091 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007092 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007093 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007094 curproxy->conf.args.file = NULL;
7095 curproxy->conf.args.line = 0;
7096 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007097
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007098 /* only now we can check if some args remain unresolved.
7099 * This must be done after the users and groups resolution.
7100 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007101 cfgerr += smp_resolve_args(curproxy);
7102 if (!cfgerr)
7103 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007104
Willy Tarreau2738a142006-07-08 17:28:09 +02007105 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007106 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007107 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007108 (!curproxy->timeout.connect ||
7109 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007110 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007111 " | While not properly invalid, you will certainly encounter various problems\n"
7112 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007113 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007114 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007115 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007116 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007117
Willy Tarreau1fa31262007-12-03 00:36:16 +01007118 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7119 * We must still support older configurations, so let's find out whether those
7120 * parameters have been set or must be copied from contimeouts.
7121 */
7122 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007123 if (!curproxy->timeout.tarpit ||
7124 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007125 /* tarpit timeout not set. We search in the following order:
7126 * default.tarpit, curr.connect, default.connect.
7127 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007128 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007129 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007130 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007131 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007132 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007133 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007134 }
7135 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007136 (!curproxy->timeout.queue ||
7137 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007138 /* queue timeout not set. We search in the following order:
7139 * default.queue, curr.connect, default.connect.
7140 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007141 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007142 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007143 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007144 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007145 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007146 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007147 }
7148 }
7149
Willy Tarreau1620ec32011-08-06 17:05:02 +02007150 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007151 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7152 curproxy->check_req = (char *)malloc(curproxy->check_len);
7153 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007154 }
7155
Willy Tarreau215663d2014-06-13 18:30:23 +02007156 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7157 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7158 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7159 proxy_type_str(curproxy), curproxy->id);
7160 err_code |= ERR_WARN;
7161 }
7162
Willy Tarreau193b8c62012-11-22 00:17:38 +01007163 /* ensure that cookie capture length is not too large */
7164 if (curproxy->capture_len >= global.tune.cookie_len) {
7165 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7166 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7167 err_code |= ERR_WARN;
7168 curproxy->capture_len = global.tune.cookie_len - 1;
7169 }
7170
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007171 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007172 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007173 curproxy->req_cap_pool = create_pool("ptrcap",
7174 curproxy->nb_req_cap * sizeof(char *),
7175 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007176 }
7177
7178 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007179 curproxy->rsp_cap_pool = create_pool("ptrcap",
7180 curproxy->nb_rsp_cap * sizeof(char *),
7181 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007182 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007183
Willy Tarreaubaaee002006-06-26 02:48:02 +02007184 /* first, we will invert the servers list order */
7185 newsrv = NULL;
7186 while (curproxy->srv) {
7187 struct server *next;
7188
7189 next = curproxy->srv->next;
7190 curproxy->srv->next = newsrv;
7191 newsrv = curproxy->srv;
7192 if (!next)
7193 break;
7194 curproxy->srv = next;
7195 }
7196
Willy Tarreau17edc812014-01-03 12:14:34 +01007197 /* Check that no server name conflicts. This causes trouble in the stats.
7198 * We only emit a warning for the first conflict affecting each server,
7199 * in order to avoid combinatory explosion if all servers have the same
7200 * name. We do that only for servers which do not have an explicit ID,
7201 * because these IDs were made also for distinguishing them and we don't
7202 * want to annoy people who correctly manage them.
7203 */
7204 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7205 struct server *other_srv;
7206
7207 if (newsrv->puid)
7208 continue;
7209
7210 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7211 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7212 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7213 newsrv->conf.file, newsrv->conf.line,
7214 proxy_type_str(curproxy), curproxy->id,
7215 newsrv->id, other_srv->conf.line);
7216 break;
7217 }
7218 }
7219 }
7220
Willy Tarreaudd701652010-05-25 23:03:02 +02007221 /* assign automatic UIDs to servers which don't have one yet */
7222 next_id = 1;
7223 newsrv = curproxy->srv;
7224 while (newsrv != NULL) {
7225 if (!newsrv->puid) {
7226 /* server ID not set, use automatic numbering with first
7227 * spare entry starting with next_svid.
7228 */
7229 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7230 newsrv->conf.id.key = newsrv->puid = next_id;
7231 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7232 }
7233 next_id++;
7234 newsrv = newsrv->next;
7235 }
7236
Willy Tarreau20697042007-11-15 23:26:18 +01007237 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007238 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007239
Willy Tarreau62c3be22012-01-20 13:12:32 +01007240 /*
7241 * If this server supports a maxconn parameter, it needs a dedicated
7242 * tasks to fill the emptied slots when a connection leaves.
7243 * Also, resolve deferred tracking dependency if needed.
7244 */
7245 newsrv = curproxy->srv;
7246 while (newsrv != NULL) {
7247 if (newsrv->minconn > newsrv->maxconn) {
7248 /* Only 'minconn' was specified, or it was higher than or equal
7249 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7250 * this will avoid further useless expensive computations.
7251 */
7252 newsrv->maxconn = newsrv->minconn;
7253 } else if (newsrv->maxconn && !newsrv->minconn) {
7254 /* minconn was not specified, so we set it to maxconn */
7255 newsrv->minconn = newsrv->maxconn;
7256 }
7257
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007258#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007259 if (newsrv->use_ssl || newsrv->check.use_ssl)
7260 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007261#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007262
Willy Tarreau2f075e92013-12-03 11:11:34 +01007263 /* set the check type on the server */
7264 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7265
Willy Tarreau62c3be22012-01-20 13:12:32 +01007266 if (newsrv->trackit) {
7267 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007268 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007269 char *pname, *sname;
7270
7271 pname = newsrv->trackit;
7272 sname = strrchr(pname, '/');
7273
7274 if (sname)
7275 *sname++ = '\0';
7276 else {
7277 sname = pname;
7278 pname = NULL;
7279 }
7280
7281 if (pname) {
7282 px = findproxy(pname, PR_CAP_BE);
7283 if (!px) {
7284 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7285 proxy_type_str(curproxy), curproxy->id,
7286 newsrv->id, pname);
7287 cfgerr++;
7288 goto next_srv;
7289 }
7290 } else
7291 px = curproxy;
7292
7293 srv = findserver(px, sname);
7294 if (!srv) {
7295 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7296 proxy_type_str(curproxy), curproxy->id,
7297 newsrv->id, sname);
7298 cfgerr++;
7299 goto next_srv;
7300 }
7301
Willy Tarreau32091232014-05-16 13:52:00 +02007302 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7303 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7304 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007305 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007306 "tracking as it does not have any check nor agent enabled.\n",
7307 proxy_type_str(curproxy), curproxy->id,
7308 newsrv->id, px->id, srv->id);
7309 cfgerr++;
7310 goto next_srv;
7311 }
7312
7313 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7314
7315 if (loop) {
7316 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7317 "belongs to a tracking chain looping back to %s/%s.\n",
7318 proxy_type_str(curproxy), curproxy->id,
7319 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007320 cfgerr++;
7321 goto next_srv;
7322 }
7323
7324 if (curproxy != px &&
7325 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7326 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7327 "tracking: disable-on-404 option inconsistency.\n",
7328 proxy_type_str(curproxy), curproxy->id,
7329 newsrv->id, px->id, srv->id);
7330 cfgerr++;
7331 goto next_srv;
7332 }
7333
7334 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007335 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007336 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007337 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007338 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007339 }
7340
7341 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007342 newsrv->tracknext = srv->trackers;
7343 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007344
7345 free(newsrv->trackit);
7346 newsrv->trackit = NULL;
7347 }
7348 next_srv:
7349 newsrv = newsrv->next;
7350 }
7351
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007352 /* We have to initialize the server lookup mechanism depending
7353 * on what LB algorithm was choosen.
7354 */
7355
7356 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7357 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7358 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007359 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7360 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7361 init_server_map(curproxy);
7362 } else {
7363 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7364 fwrr_init_server_groups(curproxy);
7365 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007366 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007367
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007368 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007369 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7370 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7371 fwlc_init_server_tree(curproxy);
7372 } else {
7373 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7374 fas_init_server_tree(curproxy);
7375 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007376 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007377
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007378 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007379 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7380 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7381 chash_init_server_tree(curproxy);
7382 } else {
7383 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7384 init_server_map(curproxy);
7385 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007386 break;
7387 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007388
7389 if (curproxy->options & PR_O_LOGASAP)
7390 curproxy->to_log &= ~LW_BYTES;
7391
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007392 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007393 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007394 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7395 proxy_type_str(curproxy), curproxy->id);
7396 err_code |= ERR_WARN;
7397 }
7398
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007399 if (curproxy->mode != PR_MODE_HTTP) {
7400 int optnum;
7401
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007402 if (curproxy->uri_auth) {
7403 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7404 proxy_type_str(curproxy), curproxy->id);
7405 err_code |= ERR_WARN;
7406 curproxy->uri_auth = NULL;
7407 }
7408
Willy Tarreau87cf5142011-08-19 22:57:24 +02007409 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007410 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7411 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7412 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007413 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007414 }
7415
7416 if (curproxy->options & PR_O_ORGTO) {
7417 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7418 "originalto", proxy_type_str(curproxy), curproxy->id);
7419 err_code |= ERR_WARN;
7420 curproxy->options &= ~PR_O_ORGTO;
7421 }
7422
7423 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7424 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7425 (curproxy->cap & cfg_opts[optnum].cap) &&
7426 (curproxy->options & cfg_opts[optnum].val)) {
7427 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7428 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7429 err_code |= ERR_WARN;
7430 curproxy->options &= ~cfg_opts[optnum].val;
7431 }
7432 }
7433
7434 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7435 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7436 (curproxy->cap & cfg_opts2[optnum].cap) &&
7437 (curproxy->options2 & cfg_opts2[optnum].val)) {
7438 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7439 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7440 err_code |= ERR_WARN;
7441 curproxy->options2 &= ~cfg_opts2[optnum].val;
7442 }
7443 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007444
Pieter Baauwd551fb52013-05-08 22:49:23 +02007445#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007446 if (curproxy->conn_src.bind_hdr_occ) {
7447 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007448 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007449 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007450 err_code |= ERR_WARN;
7451 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007452#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007453 }
7454
Willy Tarreaubaaee002006-06-26 02:48:02 +02007455 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007456 * ensure that we're not cross-dressing a TCP server into HTTP.
7457 */
7458 newsrv = curproxy->srv;
7459 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007460 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007461 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7462 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007463 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007464 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007465
Willy Tarreau0cec3312011-10-31 13:49:26 +01007466 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7467 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7468 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7469 err_code |= ERR_WARN;
7470 }
7471
Willy Tarreauc93cd162014-05-13 15:54:22 +02007472 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007473 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7474 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7475 err_code |= ERR_WARN;
7476 }
7477
Pieter Baauwd551fb52013-05-08 22:49:23 +02007478#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007479 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7480 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007481 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 +01007482 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007483 err_code |= ERR_WARN;
7484 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007485#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007486 newsrv = newsrv->next;
7487 }
7488
Willy Tarreaue42bd962014-09-16 16:21:19 +02007489 /* check if we have a frontend with "tcp-request content" looking at L7
7490 * with no inspect-delay
7491 */
7492 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7493 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7494 if (trule->action == TCP_ACT_CAPTURE &&
7495 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7496 break;
7497 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7498 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7499 break;
7500 }
7501
7502 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7503 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7504 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7505 " This means that these rules will randomly find their contents. This can be fixed by"
7506 " setting the tcp-request inspect-delay.\n",
7507 proxy_type_str(curproxy), curproxy->id);
7508 err_code |= ERR_WARN;
7509 }
7510 }
7511
Willy Tarreauc1a21672009-08-16 22:37:44 +02007512 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007513 if (!curproxy->accept)
7514 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007515
Willy Tarreauc1a21672009-08-16 22:37:44 +02007516 if (curproxy->tcp_req.inspect_delay ||
7517 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007518 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007519
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007520 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007521 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007522 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007523 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007524
7525 /* both TCP and HTTP must check switching rules */
7526 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7527 }
7528
7529 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007530 if (curproxy->tcp_req.inspect_delay ||
7531 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7532 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7533
Emeric Brun97679e72010-09-23 17:56:44 +02007534 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7535 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7536
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007537 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007538 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007539 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007540 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007541
7542 /* If the backend does requires RDP cookie persistence, we have to
7543 * enable the corresponding analyser.
7544 */
7545 if (curproxy->options2 & PR_O2_RDPC_PRST)
7546 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7547 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007548 }
7549
7550 /***********************************************************/
7551 /* At this point, target names have already been resolved. */
7552 /***********************************************************/
7553
7554 /* Check multi-process mode compatibility */
7555
7556 if (global.nbproc > 1 && global.stats_fe) {
7557 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7558 unsigned long mask;
7559
7560 mask = nbits(global.nbproc);
7561 if (global.stats_fe->bind_proc)
7562 mask &= global.stats_fe->bind_proc;
7563
7564 if (bind_conf->bind_proc)
7565 mask &= bind_conf->bind_proc;
7566
7567 /* stop here if more than one process is used */
7568 if (popcount(mask) > 1)
7569 break;
7570 }
7571 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7572 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");
7573 }
7574 }
7575
7576 /* Make each frontend inherit bind-process from its listeners when not specified. */
7577 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7578 if (curproxy->bind_proc)
7579 continue;
7580
7581 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7582 unsigned long mask;
7583
7584 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7585 curproxy->bind_proc |= mask;
7586 }
7587
7588 if (!curproxy->bind_proc)
7589 curproxy->bind_proc = ~0UL;
7590 }
7591
7592 if (global.stats_fe) {
7593 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7594 unsigned long mask;
7595
7596 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7597 global.stats_fe->bind_proc |= mask;
7598 }
7599 if (!global.stats_fe->bind_proc)
7600 global.stats_fe->bind_proc = ~0UL;
7601 }
7602
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007603 /* propagate bindings from frontends to backends. Don't do it if there
7604 * are any fatal errors as we must not call it with unresolved proxies.
7605 */
7606 if (!cfgerr) {
7607 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7608 if (curproxy->cap & PR_CAP_FE)
7609 propagate_processes(curproxy, NULL);
7610 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007611 }
7612
7613 /* Bind each unbound backend to all processes when not specified. */
7614 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7615 if (curproxy->bind_proc)
7616 continue;
7617 curproxy->bind_proc = ~0UL;
7618 }
7619
7620 /*******************************************************/
7621 /* At this step, all proxies have a non-null bind_proc */
7622 /*******************************************************/
7623
7624 /* perform the final checks before creating tasks */
7625
7626 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7627 struct listener *listener;
7628 unsigned int next_id;
7629 int nbproc;
7630
7631 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007632
Emeric Brunc52962f2012-11-15 18:28:02 +01007633#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007634 /* Configure SSL for each bind line.
7635 * Note: if configuration fails at some point, the ->ctx member
7636 * remains NULL so that listeners can later detach.
7637 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007638 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007639 int alloc_ctx;
7640
Emeric Brunc52962f2012-11-15 18:28:02 +01007641 if (!bind_conf->is_ssl) {
7642 if (bind_conf->default_ctx) {
7643 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7644 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7645 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007646 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007647 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007648 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007649 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007650 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007651 cfgerr++;
7652 continue;
7653 }
7654
Emeric Brun8dc60392014-05-09 13:52:00 +02007655 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007656 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007657 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7658 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");
7659 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007660 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007661 cfgerr++;
7662 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007663 }
7664
Emeric Brunfc0421f2012-09-07 17:30:07 +02007665 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007666 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007667 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007668#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007669
Willy Tarreaue6b98942007-10-29 01:09:36 +01007670 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007671 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007672 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007673 if (!listener->luid) {
7674 /* listener ID not set, use automatic numbering with first
7675 * spare entry starting with next_luid.
7676 */
7677 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7678 listener->conf.id.key = listener->luid = next_id;
7679 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007680 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007681 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007682
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007683 /* enable separate counters */
7684 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7685 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007686 if (!listener->name)
7687 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007688 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007689
Willy Tarreaue6b98942007-10-29 01:09:36 +01007690 if (curproxy->options & PR_O_TCP_NOLING)
7691 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007692 if (!listener->maxconn)
7693 listener->maxconn = curproxy->maxconn;
7694 if (!listener->backlog)
7695 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007696 if (!listener->maxaccept)
7697 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7698
7699 /* we want to have an optimal behaviour on single process mode to
7700 * maximize the work at once, but in multi-process we want to keep
7701 * some fairness between processes, so we target half of the max
7702 * number of events to be balanced over all the processes the proxy
7703 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7704 * used to disable the limit.
7705 */
7706 if (listener->maxaccept > 0) {
7707 if (nbproc > 1)
7708 listener->maxaccept = (listener->maxaccept + 1) / 2;
7709 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7710 }
7711
Willy Tarreau9903f0e2015-04-04 18:50:31 +02007712 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02007713 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007714 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01007715 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007716
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007717 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7718 listener->options |= LI_O_TCP_RULES;
7719
Willy Tarreaude3041d2010-05-31 10:56:17 +02007720 if (curproxy->mon_mask.s_addr)
7721 listener->options |= LI_O_CHK_MONNET;
7722
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007723 /* smart accept mode is automatic in HTTP mode */
7724 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007725 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007726 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7727 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007728 }
7729
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007730 /* Release unused SSL configs */
7731 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7732 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007733 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007734#ifdef USE_OPENSSL
7735 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007736 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007737 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007738 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007739 free(bind_conf->crl_file);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007740 free(bind_conf->tls_ticket_keys);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007741#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007742 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007743
Willy Tarreau102df612014-05-07 23:56:38 +02007744 if (nbproc > 1) {
7745 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02007746 int count, maxproc = 0;
7747
7748 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7749 count = popcount(bind_conf->bind_proc);
7750 if (count > maxproc)
7751 maxproc = count;
7752 }
7753 /* backends have 0, frontends have 1 or more */
7754 if (maxproc != 1)
7755 Warning("Proxy '%s': in multi-process mode, stats will be"
7756 " limited to process assigned to the current request.\n",
7757 curproxy->id);
7758
Willy Tarreau102df612014-05-07 23:56:38 +02007759 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7760 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7761 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007762 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007763 }
Willy Tarreau102df612014-05-07 23:56:38 +02007764 if (curproxy->appsession_name) {
7765 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7766 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007767 }
Willy Tarreau102df612014-05-07 23:56:38 +02007768 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7769 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7770 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007771 }
7772 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007773
7774 /* create the task associated with the proxy */
7775 curproxy->task = task_new();
7776 if (curproxy->task) {
7777 curproxy->task->context = curproxy;
7778 curproxy->task->process = manage_proxy;
7779 /* no need to queue, it will be done automatically if some
7780 * listener gets limited.
7781 */
7782 curproxy->task->expire = TICK_ETERNITY;
7783 } else {
7784 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7785 curproxy->id);
7786 cfgerr++;
7787 }
Willy Tarreaub369a042014-09-16 13:21:03 +02007788 }
7789
Willy Tarreaufbb78422011-06-05 15:38:35 +02007790 /* automatically compute fullconn if not set. We must not do it in the
7791 * loop above because cross-references are not yet fully resolved.
7792 */
7793 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7794 /* If <fullconn> is not set, let's set it to 10% of the sum of
7795 * the possible incoming frontend's maxconns.
7796 */
7797 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7798 struct proxy *fe;
7799 int total = 0;
7800
7801 /* sum up the number of maxconns of frontends which
7802 * reference this backend at least once or which are
7803 * the same one ('listen').
7804 */
7805 for (fe = proxy; fe; fe = fe->next) {
7806 struct switching_rule *rule;
7807 struct hdr_exp *exp;
7808 int found = 0;
7809
7810 if (!(fe->cap & PR_CAP_FE))
7811 continue;
7812
7813 if (fe == curproxy) /* we're on a "listen" instance */
7814 found = 1;
7815
7816 if (fe->defbe.be == curproxy) /* "default_backend" */
7817 found = 1;
7818
7819 /* check if a "use_backend" rule matches */
7820 if (!found) {
7821 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007822 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007823 found = 1;
7824 break;
7825 }
7826 }
7827 }
7828
7829 /* check if a "reqsetbe" rule matches */
7830 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7831 if (exp->action == ACT_SETBE &&
7832 (struct proxy *)exp->replace == curproxy) {
7833 found = 1;
7834 break;
7835 }
7836 }
7837
7838 /* now we've checked all possible ways to reference a backend
7839 * from a frontend.
7840 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007841 if (!found)
7842 continue;
7843 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007844 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007845 /* we have the sum of the maxconns in <total>. We only
7846 * keep 10% of that sum to set the default fullconn, with
7847 * a hard minimum of 1 (to avoid a divide by zero).
7848 */
7849 curproxy->fullconn = (total + 9) / 10;
7850 if (!curproxy->fullconn)
7851 curproxy->fullconn = 1;
7852 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007853 }
7854
Willy Tarreau056f5682010-06-06 15:51:11 +02007855 /* initialize stick-tables on backend capable proxies. This must not
7856 * be done earlier because the data size may be discovered while parsing
7857 * other proxies.
7858 */
Godbach9703e662013-12-11 21:11:41 +08007859 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007860 if (curproxy->state == PR_STSTOPPED)
7861 continue;
7862
Godbach9703e662013-12-11 21:11:41 +08007863 if (!stktable_init(&curproxy->table)) {
7864 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7865 cfgerr++;
7866 }
7867 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007868
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007869 /*
7870 * Recount currently required checks.
7871 */
7872
7873 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7874 int optnum;
7875
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007876 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7877 if (curproxy->options & cfg_opts[optnum].val)
7878 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007879
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007880 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7881 if (curproxy->options2 & cfg_opts2[optnum].val)
7882 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007883 }
7884
Willy Tarreau122541c2011-09-07 21:24:49 +02007885 if (peers) {
7886 struct peers *curpeers = peers, **last;
7887 struct peer *p, *pb;
7888
7889 /* Remove all peers sections which don't have a valid listener.
7890 * This can happen when a peers section is never referenced and
7891 * does not contain a local peer.
7892 */
7893 last = &peers;
7894 while (*last) {
7895 curpeers = *last;
7896 if (curpeers->peers_fe) {
7897 last = &curpeers->next;
7898 continue;
7899 }
7900
7901 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7902 curpeers->id, localpeer);
7903
7904 p = curpeers->remote;
7905 while (p) {
7906 pb = p->next;
7907 free(p->id);
7908 free(p);
7909 p = pb;
7910 }
7911
7912 /* Destroy and unlink this curpeers section.
7913 * Note: curpeers is backed up into *last.
7914 */
7915 free(curpeers->id);
7916 curpeers = curpeers->next;
7917 free(*last);
7918 *last = curpeers;
7919 }
7920 }
7921
Simon Horman0d16a402015-01-30 11:22:58 +09007922 if (mailers) {
7923 struct mailers *curmailers = mailers, **last;
7924 struct mailer *m, *mb;
7925
7926 /* Remove all mailers sections which don't have a valid listener.
7927 * This can happen when a mailers section is never referenced.
7928 */
7929 last = &mailers;
7930 while (*last) {
7931 curmailers = *last;
7932 if (curmailers->users) {
7933 last = &curmailers->next;
7934 continue;
7935 }
7936
7937 Warning("Removing incomplete section 'mailers %s'.\n",
7938 curmailers->id);
7939
7940 m = curmailers->mailer_list;
7941 while (m) {
7942 mb = m->next;
7943 free(m->id);
7944 free(m);
7945 m = mb;
7946 }
7947
7948 /* Destroy and unlink this curmailers section.
7949 * Note: curmailers is backed up into *last.
7950 */
7951 free(curmailers->id);
7952 curmailers = curmailers->next;
7953 free(*last);
7954 *last = curmailers;
7955 }
7956 }
7957
Willy Tarreau34eb6712011-10-24 18:15:04 +02007958 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007959 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007960 MEM_F_SHARED);
7961
Willy Tarreaubb925012009-07-23 13:36:36 +02007962 if (cfgerr > 0)
7963 err_code |= ERR_ALERT | ERR_FATAL;
7964 out:
7965 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007966}
7967
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007968/*
7969 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7970 * parsing sessions.
7971 */
7972void cfg_register_keywords(struct cfg_kw_list *kwl)
7973{
7974 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7975}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007976
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007977/*
7978 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7979 */
7980void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7981{
7982 LIST_DEL(&kwl->list);
7983 LIST_INIT(&kwl->list);
7984}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007985
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007986/* this function register new section in the haproxy configuration file.
7987 * <section_name> is the name of this new section and <section_parser>
7988 * is the called parser. If two section declaration have the same name,
7989 * only the first declared is used.
7990 */
7991int cfg_register_section(char *section_name,
7992 int (*section_parser)(const char *, int, char **, int))
7993{
7994 struct cfg_section *cs;
7995
7996 cs = calloc(1, sizeof(*cs));
7997 if (!cs) {
7998 Alert("register section '%s': out of memory.\n", section_name);
7999 return 0;
8000 }
8001
8002 cs->section_name = section_name;
8003 cs->section_parser = section_parser;
8004
8005 LIST_ADDQ(&sections, &cs->list);
8006
8007 return 1;
8008}
8009
Willy Tarreaubaaee002006-06-26 02:48:02 +02008010/*
8011 * Local variables:
8012 * c-indent-level: 8
8013 * c-basic-offset: 8
8014 * End:
8015 */