blob: 4f75256de580c36d6be34b47cab3331829cb7055 [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 Tarreauf3045d22015-04-29 16:24:50 +0200910 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
911 if (*args[1]) {
912 global.tune.pattern_cache = atoi(args[1]);
913 if (global.tune.pattern_cache < 0) {
914 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
915 file, linenum, args[0]);
916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
918 }
919 } else {
920 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
921 file, linenum, args[0]);
922 err_code |= ERR_ALERT | ERR_FATAL;
923 goto out;
924 }
925 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 else if (!strcmp(args[0], "uid")) {
927 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200928 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200929 err_code |= ERR_ALERT;
930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200931 }
932 if (*(args[1]) == 0) {
933 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200934 err_code |= ERR_ALERT | ERR_FATAL;
935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936 }
937 global.uid = atol(args[1]);
938 }
939 else if (!strcmp(args[0], "gid")) {
940 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200941 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200942 err_code |= ERR_ALERT;
943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200944 }
945 if (*(args[1]) == 0) {
946 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200947 err_code |= ERR_ALERT | ERR_FATAL;
948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949 }
950 global.gid = atol(args[1]);
951 }
Simon Horman98637e52014-06-20 12:30:16 +0900952 else if (!strcmp(args[0], "external-check")) {
953 global.external_check = 1;
954 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200955 /* user/group name handling */
956 else if (!strcmp(args[0], "user")) {
957 struct passwd *ha_user;
958 if (global.uid != 0) {
959 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200960 err_code |= ERR_ALERT;
961 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200962 }
963 errno = 0;
964 ha_user = getpwnam(args[1]);
965 if (ha_user != NULL) {
966 global.uid = (int)ha_user->pw_uid;
967 }
968 else {
969 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 +0200970 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200971 }
972 }
973 else if (!strcmp(args[0], "group")) {
974 struct group *ha_group;
975 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200976 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200977 err_code |= ERR_ALERT;
978 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200979 }
980 errno = 0;
981 ha_group = getgrnam(args[1]);
982 if (ha_group != NULL) {
983 global.gid = (int)ha_group->gr_gid;
984 }
985 else {
986 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 +0200987 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200988 }
989 }
990 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200991 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 if (*(args[1]) == 0) {
993 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200994 err_code |= ERR_ALERT | ERR_FATAL;
995 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200996 }
997 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100998 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
999 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1000 file, linenum, args[0], LONGBITS, global.nbproc);
1001 err_code |= ERR_ALERT | ERR_FATAL;
1002 goto out;
1003 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001004 }
1005 else if (!strcmp(args[0], "maxconn")) {
1006 if (global.maxconn != 0) {
1007 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001008 err_code |= ERR_ALERT;
1009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001010 }
1011 if (*(args[1]) == 0) {
1012 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001013 err_code |= ERR_ALERT | ERR_FATAL;
1014 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001015 }
1016 global.maxconn = atol(args[1]);
1017#ifdef SYSTEM_MAXCONN
1018 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1019 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);
1020 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001021 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001022 }
1023#endif /* SYSTEM_MAXCONN */
1024 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001025 else if (!strcmp(args[0], "maxsslconn")) {
1026#ifdef USE_OPENSSL
1027 if (*(args[1]) == 0) {
1028 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1029 err_code |= ERR_ALERT | ERR_FATAL;
1030 goto out;
1031 }
1032 global.maxsslconn = atol(args[1]);
1033#else
Emeric Brun0914df82012-10-02 18:45:42 +02001034 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1035 err_code |= ERR_ALERT | ERR_FATAL;
1036 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001037#endif
1038 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001039 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1040#ifdef USE_OPENSSL
1041 if (*(args[1]) == 0) {
1042 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1043 err_code |= ERR_ALERT | ERR_FATAL;
1044 goto out;
1045 }
1046 free(global.listen_default_ciphers);
1047 global.listen_default_ciphers = strdup(args[1]);
1048#else
1049 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1050 err_code |= ERR_ALERT | ERR_FATAL;
1051 goto out;
1052#endif
1053 }
1054 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1055#ifdef USE_OPENSSL
1056 if (*(args[1]) == 0) {
1057 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1058 err_code |= ERR_ALERT | ERR_FATAL;
1059 goto out;
1060 }
1061 free(global.connect_default_ciphers);
1062 global.connect_default_ciphers = strdup(args[1]);
1063#else
1064 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1065 err_code |= ERR_ALERT | ERR_FATAL;
1066 goto out;
1067#endif
1068 }
Emeric Brun850efd52014-01-29 12:24:34 +01001069 else if (!strcmp(args[0], "ssl-server-verify")) {
1070 if (*(args[1]) == 0) {
1071 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1072 err_code |= ERR_ALERT | ERR_FATAL;
1073 goto out;
1074 }
1075 if (strcmp(args[1],"none") == 0)
1076 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1077 else if (strcmp(args[1],"required") == 0)
1078 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1079 else {
1080 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1081 err_code |= ERR_ALERT | ERR_FATAL;
1082 goto out;
1083 }
1084 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001085 else if (!strcmp(args[0], "maxconnrate")) {
1086 if (global.cps_lim != 0) {
1087 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1088 err_code |= ERR_ALERT;
1089 goto out;
1090 }
1091 if (*(args[1]) == 0) {
1092 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto out;
1095 }
1096 global.cps_lim = atol(args[1]);
1097 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001098 else if (!strcmp(args[0], "maxsessrate")) {
1099 if (global.sps_lim != 0) {
1100 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1101 err_code |= ERR_ALERT;
1102 goto out;
1103 }
1104 if (*(args[1]) == 0) {
1105 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1106 err_code |= ERR_ALERT | ERR_FATAL;
1107 goto out;
1108 }
1109 global.sps_lim = atol(args[1]);
1110 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001111 else if (!strcmp(args[0], "maxsslrate")) {
1112 if (global.ssl_lim != 0) {
1113 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1114 err_code |= ERR_ALERT;
1115 goto out;
1116 }
1117 if (*(args[1]) == 0) {
1118 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1119 err_code |= ERR_ALERT | ERR_FATAL;
1120 goto out;
1121 }
1122 global.ssl_lim = atol(args[1]);
1123 }
William Lallemandd85f9172012-11-09 17:05:39 +01001124 else if (!strcmp(args[0], "maxcomprate")) {
1125 if (*(args[1]) == 0) {
1126 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1127 err_code |= ERR_ALERT | ERR_FATAL;
1128 goto out;
1129 }
1130 global.comp_rate_lim = atoi(args[1]) * 1024;
1131 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001132 else if (!strcmp(args[0], "maxpipes")) {
1133 if (global.maxpipes != 0) {
1134 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001135 err_code |= ERR_ALERT;
1136 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001137 }
1138 if (*(args[1]) == 0) {
1139 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001140 err_code |= ERR_ALERT | ERR_FATAL;
1141 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001142 }
1143 global.maxpipes = atol(args[1]);
1144 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001145 else if (!strcmp(args[0], "maxzlibmem")) {
1146 if (*(args[1]) == 0) {
1147 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1148 err_code |= ERR_ALERT | ERR_FATAL;
1149 goto out;
1150 }
William Lallemande3a7d992012-11-20 11:25:20 +01001151 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001152 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001153 else if (!strcmp(args[0], "maxcompcpuusage")) {
1154 if (*(args[1]) == 0) {
1155 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1156 err_code |= ERR_ALERT | ERR_FATAL;
1157 goto out;
1158 }
1159 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001160 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001161 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1162 err_code |= ERR_ALERT | ERR_FATAL;
1163 goto out;
1164 }
1165}
1166
Willy Tarreaubaaee002006-06-26 02:48:02 +02001167 else if (!strcmp(args[0], "ulimit-n")) {
1168 if (global.rlimit_nofile != 0) {
1169 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001170 err_code |= ERR_ALERT;
1171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001172 }
1173 if (*(args[1]) == 0) {
1174 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001175 err_code |= ERR_ALERT | ERR_FATAL;
1176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001177 }
1178 global.rlimit_nofile = atol(args[1]);
1179 }
1180 else if (!strcmp(args[0], "chroot")) {
1181 if (global.chroot != NULL) {
1182 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001183 err_code |= ERR_ALERT;
1184 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001185 }
1186 if (*(args[1]) == 0) {
1187 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001188 err_code |= ERR_ALERT | ERR_FATAL;
1189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001190 }
1191 global.chroot = strdup(args[1]);
1192 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001193 else if (!strcmp(args[0], "description")) {
1194 int i, len=0;
1195 char *d;
1196
1197 if (!*args[1]) {
1198 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1199 file, linenum, args[0]);
1200 err_code |= ERR_ALERT | ERR_FATAL;
1201 goto out;
1202 }
1203
Willy Tarreau348acfe2014-04-14 15:00:39 +02001204 for (i = 1; *args[i]; i++)
1205 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001206
1207 if (global.desc)
1208 free(global.desc);
1209
1210 global.desc = d = (char *)calloc(1, len);
1211
Willy Tarreau348acfe2014-04-14 15:00:39 +02001212 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1213 for (i = 2; *args[i]; i++)
1214 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001215 }
1216 else if (!strcmp(args[0], "node")) {
1217 int i;
1218 char c;
1219
1220 for (i=0; args[1][i]; i++) {
1221 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001222 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1223 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001224 break;
1225 }
1226
1227 if (!i || args[1][i]) {
1228 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1229 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1230 file, linenum, args[0]);
1231 err_code |= ERR_ALERT | ERR_FATAL;
1232 goto out;
1233 }
1234
1235 if (global.node)
1236 free(global.node);
1237
1238 global.node = strdup(args[1]);
1239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001240 else if (!strcmp(args[0], "pidfile")) {
1241 if (global.pidfile != NULL) {
1242 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001243 err_code |= ERR_ALERT;
1244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001245 }
1246 if (*(args[1]) == 0) {
1247 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001248 err_code |= ERR_ALERT | ERR_FATAL;
1249 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001250 }
1251 global.pidfile = strdup(args[1]);
1252 }
Emeric Bruned760922010-10-22 17:59:25 +02001253 else if (!strcmp(args[0], "unix-bind")) {
1254 int cur_arg = 1;
1255 while (*(args[cur_arg])) {
1256 if (!strcmp(args[cur_arg], "prefix")) {
1257 if (global.unix_bind.prefix != NULL) {
1258 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1259 err_code |= ERR_ALERT;
1260 cur_arg += 2;
1261 continue;
1262 }
1263
1264 if (*(args[cur_arg+1]) == 0) {
1265 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1266 err_code |= ERR_ALERT | ERR_FATAL;
1267 goto out;
1268 }
1269 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1270 cur_arg += 2;
1271 continue;
1272 }
1273
1274 if (!strcmp(args[cur_arg], "mode")) {
1275
1276 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1277 cur_arg += 2;
1278 continue;
1279 }
1280
1281 if (!strcmp(args[cur_arg], "uid")) {
1282
1283 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1284 cur_arg += 2;
1285 continue;
1286 }
1287
1288 if (!strcmp(args[cur_arg], "gid")) {
1289
1290 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1291 cur_arg += 2;
1292 continue;
1293 }
1294
1295 if (!strcmp(args[cur_arg], "user")) {
1296 struct passwd *user;
1297
1298 user = getpwnam(args[cur_arg + 1]);
1299 if (!user) {
1300 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\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.uid = user->pw_uid;
1307 cur_arg += 2;
1308 continue;
1309 }
1310
1311 if (!strcmp(args[cur_arg], "group")) {
1312 struct group *group;
1313
1314 group = getgrnam(args[cur_arg + 1]);
1315 if (!group) {
1316 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1317 file, linenum, args[0], args[cur_arg + 1 ]);
1318 err_code |= ERR_ALERT | ERR_FATAL;
1319 goto out;
1320 }
1321
1322 global.unix_bind.ux.gid = group->gr_gid;
1323 cur_arg += 2;
1324 continue;
1325 }
1326
Willy Tarreaub48f9582011-09-05 01:17:06 +02001327 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001328 file, linenum, args[0]);
1329 err_code |= ERR_ALERT | ERR_FATAL;
1330 goto out;
1331 }
1332 }
William Lallemand0f99e342011-10-12 17:50:54 +02001333 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1334 /* delete previous herited or defined syslog servers */
1335 struct logsrv *back;
1336 struct logsrv *tmp;
1337
1338 if (*(args[1]) != 0) {
1339 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1340 err_code |= ERR_ALERT | ERR_FATAL;
1341 goto out;
1342 }
1343
1344 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1345 LIST_DEL(&tmp->list);
1346 free(tmp);
1347 }
1348 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001350 struct sockaddr_storage *sk;
1351 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001352 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001353 int arg = 0;
1354 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001355
Willy Tarreaubaaee002006-06-26 02:48:02 +02001356 if (*(args[1]) == 0 || *(args[2]) == 0) {
1357 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001358 err_code |= ERR_ALERT | ERR_FATAL;
1359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001360 }
William Lallemand0f99e342011-10-12 17:50:54 +02001361
1362 logsrv = calloc(1, sizeof(struct logsrv));
1363
Willy Tarreau18324f52014-06-27 18:10:07 +02001364 /* just after the address, a length may be specified */
1365 if (strcmp(args[arg+2], "len") == 0) {
1366 len = atoi(args[arg+3]);
1367 if (len < 80 || len > 65535) {
1368 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1369 file, linenum, args[arg+3]);
1370 err_code |= ERR_ALERT | ERR_FATAL;
1371 goto out;
1372 }
1373 logsrv->maxlen = len;
1374
1375 /* skip these two args */
1376 arg += 2;
1377 }
1378 else
1379 logsrv->maxlen = MAX_SYSLOG_LEN;
1380
1381 if (logsrv->maxlen > global.max_syslog_len) {
1382 global.max_syslog_len = logsrv->maxlen;
1383 logline = realloc(logline, global.max_syslog_len + 1);
1384 }
1385
1386 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001387 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001388 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001389 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001390 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391 }
1392
William Lallemand0f99e342011-10-12 17:50:54 +02001393 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001394 if (*(args[arg+3])) {
1395 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001396 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001397 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001398 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001399 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400 }
1401 }
1402
William Lallemand0f99e342011-10-12 17:50:54 +02001403 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001404 if (*(args[arg+4])) {
1405 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001406 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001407 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001408 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001409 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001410 }
1411 }
1412
Willy Tarreau902636f2013-03-10 19:44:48 +01001413 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001414 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001415 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001416 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001417 free(logsrv);
1418 goto out;
1419 }
1420 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001421
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001422 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001423 if (port1 != port2) {
1424 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1425 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001426 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001427 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001428 goto out;
1429 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001430
William Lallemand0f99e342011-10-12 17:50:54 +02001431 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001432 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001433 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001434 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001435
William Lallemand0f99e342011-10-12 17:50:54 +02001436 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001437 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001438 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1439 char *name;
1440 int len;
1441
1442 if (global.log_send_hostname != NULL) {
1443 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1444 err_code |= ERR_ALERT;
1445 goto out;
1446 }
1447
1448 if (*(args[1]))
1449 name = args[1];
1450 else
1451 name = hostname;
1452
1453 len = strlen(name);
1454
1455 /* We'll add a space after the name to respect the log format */
1456 free(global.log_send_hostname);
1457 global.log_send_hostname = malloc(len + 2);
1458 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1459 }
Kevinm48936af2010-12-22 16:08:21 +00001460 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1461 if (*(args[1]) == 0) {
1462 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1463 err_code |= ERR_ALERT | ERR_FATAL;
1464 goto out;
1465 }
1466 free(global.log_tag);
1467 global.log_tag = strdup(args[1]);
1468 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001469 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1470 if (global.spread_checks != 0) {
1471 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001472 err_code |= ERR_ALERT;
1473 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001474 }
1475 if (*(args[1]) == 0) {
1476 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001477 err_code |= ERR_ALERT | ERR_FATAL;
1478 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001479 }
1480 global.spread_checks = atol(args[1]);
1481 if (global.spread_checks < 0 || global.spread_checks > 50) {
1482 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001483 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001484 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001485 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001486 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1487 const char *err;
1488 unsigned int val;
1489
1490
1491 if (*(args[1]) == 0) {
1492 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1493 err_code |= ERR_ALERT | ERR_FATAL;
1494 goto out;
1495 }
1496
1497 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1498 if (err) {
1499 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1500 err_code |= ERR_ALERT | ERR_FATAL;
1501 }
1502 global.max_spread_checks = val;
1503 if (global.max_spread_checks < 0) {
1504 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1505 err_code |= ERR_ALERT | ERR_FATAL;
1506 }
1507 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001508 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1509#ifdef USE_CPU_AFFINITY
1510 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001511 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001512 unsigned long cpus = 0;
1513
1514 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001515 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001516 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001517 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001518 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001519 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001520 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001521 proc = atol(args[1]);
1522 if (proc >= 1 && proc <= LONGBITS)
1523 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001524 }
1525
1526 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001527 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",
1528 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001529 err_code |= ERR_ALERT | ERR_FATAL;
1530 goto out;
1531 }
1532
1533 cur_arg = 2;
1534 while (*args[cur_arg]) {
1535 unsigned int low, high;
1536
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001537 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001538 char *dash = strchr(args[cur_arg], '-');
1539
1540 low = high = str2uic(args[cur_arg]);
1541 if (dash)
1542 high = str2uic(dash + 1);
1543
1544 if (high < low) {
1545 unsigned int swap = low;
1546 low = high;
1547 high = swap;
1548 }
1549
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001550 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001551 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001552 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001553 err_code |= ERR_ALERT | ERR_FATAL;
1554 goto out;
1555 }
1556
1557 while (low <= high)
1558 cpus |= 1UL << low++;
1559 }
1560 else {
1561 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1562 file, linenum, args[0], args[cur_arg]);
1563 err_code |= ERR_ALERT | ERR_FATAL;
1564 goto out;
1565 }
1566 cur_arg++;
1567 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001568 for (i = 0; i < LONGBITS; i++)
1569 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001570 global.cpu_map[i] = cpus;
1571#else
1572 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1573 err_code |= ERR_ALERT | ERR_FATAL;
1574 goto out;
1575#endif
1576 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001577 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001578 struct cfg_kw_list *kwl;
1579 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001580 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001581
1582 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1583 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1584 if (kwl->kw[index].section != CFG_GLOBAL)
1585 continue;
1586 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001587 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001588 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001589 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001590 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001591 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001592 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001593 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001594 err_code |= ERR_WARN;
1595 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001596 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001597 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001598 }
1599 }
1600 }
1601
Willy Tarreaubaaee002006-06-26 02:48:02 +02001602 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001603 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001604 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001605
Willy Tarreau058e9072009-07-20 09:30:05 +02001606 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001607 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001608 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609}
1610
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001611void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001612{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001613 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001614 defproxy.mode = PR_MODE_TCP;
1615 defproxy.state = PR_STNEW;
1616 defproxy.maxconn = cfg_maxpconn;
1617 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001618
Simon Horman66183002013-02-23 10:16:43 +09001619 defproxy.defsrv.check.inter = DEF_CHKINTR;
1620 defproxy.defsrv.check.fastinter = 0;
1621 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001622 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1623 defproxy.defsrv.agent.fastinter = 0;
1624 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001625 defproxy.defsrv.check.rise = DEF_RISETIME;
1626 defproxy.defsrv.check.fall = DEF_FALLTIME;
1627 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1628 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001629 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001630 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001631 defproxy.defsrv.maxqueue = 0;
1632 defproxy.defsrv.minconn = 0;
1633 defproxy.defsrv.maxconn = 0;
1634 defproxy.defsrv.slowstart = 0;
1635 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1636 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1637 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001638
1639 defproxy.email_alert.level = LOG_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640}
1641
Willy Tarreauade5ec42010-01-28 19:33:49 +01001642
Willy Tarreau63af98d2014-05-18 08:11:41 +02001643/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1644 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1645 * ERR_FATAL in case of error.
1646 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001647static int create_cond_regex_rule(const char *file, int line,
1648 struct proxy *px, int dir, int action, int flags,
1649 const char *cmd, const char *reg, const char *repl,
1650 const char **cond_start)
1651{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001652 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001653 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001654 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001655 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001656 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001657 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001658 int cs;
1659 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001660
1661 if (px == &defproxy) {
1662 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001663 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001664 goto err;
1665 }
1666
1667 if (*reg == 0) {
1668 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001669 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001670 goto err;
1671 }
1672
1673 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001674 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001675
Willy Tarreau5321c422010-01-28 20:35:13 +01001676 if (cond_start &&
1677 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001678 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1679 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1680 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001681 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001682 goto err;
1683 }
1684 }
1685 else if (cond_start && **cond_start) {
1686 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1687 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001688 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001689 goto err;
1690 }
1691
Willy Tarreau63af98d2014-05-18 08:11:41 +02001692 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001693 (dir == SMP_OPT_DIR_REQ) ?
1694 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1695 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1696 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001697
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001698 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001699 if (!preg) {
1700 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001701 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001702 goto err;
1703 }
1704
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001705 cs = !(flags & REG_ICASE);
1706 cap = !(flags & REG_NOSUB);
1707 error = NULL;
1708 if (!regex_comp(reg, preg, cs, cap, &error)) {
1709 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1710 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001711 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001712 goto err;
1713 }
1714
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001715 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001716 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001717 if (repl && err) {
1718 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1719 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001720 ret_code |= ERR_ALERT | ERR_FATAL;
1721 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001722 }
1723
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001724 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001725 ret_code |= ERR_WARN;
1726
1727 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001728
Willy Tarreau63af98d2014-05-18 08:11:41 +02001729 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001730 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001731 err:
1732 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001733 free(errmsg);
1734 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001735}
1736
Willy Tarreaubaaee002006-06-26 02:48:02 +02001737/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001738 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001739 * Returns the error code, 0 if OK, or any combination of :
1740 * - ERR_ABORT: must abort ASAP
1741 * - ERR_FATAL: we can continue parsing but not start the service
1742 * - ERR_WARN: a warning has been emitted
1743 * - ERR_ALERT: an alert has been emitted
1744 * Only the two first ones can stop processing, the two others are just
1745 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001746 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001747int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1748{
1749 static struct peers *curpeers = NULL;
1750 struct peer *newpeer = NULL;
1751 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001752 struct bind_conf *bind_conf;
1753 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001754 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001755 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001756
1757 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001758 if (!*args[1]) {
1759 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001760 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001761 goto out;
1762 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001763
1764 err = invalid_char(args[1]);
1765 if (err) {
1766 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1767 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001768 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001769 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001770 }
1771
1772 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1773 /*
1774 * If there are two proxies with the same name only following
1775 * combinations are allowed:
1776 */
1777 if (strcmp(curpeers->id, args[1]) == 0) {
1778 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1779 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1780 err_code |= ERR_WARN;
1781 }
1782 }
1783
1784 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1785 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1786 err_code |= ERR_ALERT | ERR_ABORT;
1787 goto out;
1788 }
1789
1790 curpeers->next = peers;
1791 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001792 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001793 curpeers->conf.line = linenum;
1794 curpeers->last_change = now.tv_sec;
1795 curpeers->id = strdup(args[1]);
1796 }
1797 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001798 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001799 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001800 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001801
1802 if (!*args[2]) {
1803 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1804 file, linenum, args[0]);
1805 err_code |= ERR_ALERT | ERR_FATAL;
1806 goto out;
1807 }
1808
1809 err = invalid_char(args[1]);
1810 if (err) {
1811 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1812 file, linenum, *err, args[1]);
1813 err_code |= ERR_ALERT | ERR_FATAL;
1814 goto out;
1815 }
1816
1817 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1818 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1819 err_code |= ERR_ALERT | ERR_ABORT;
1820 goto out;
1821 }
1822
1823 /* the peers are linked backwards first */
1824 curpeers->count++;
1825 newpeer->next = curpeers->remote;
1826 curpeers->remote = newpeer;
1827 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001828 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001829 newpeer->conf.line = linenum;
1830
1831 newpeer->last_change = now.tv_sec;
1832 newpeer->id = strdup(args[1]);
1833
Willy Tarreau902636f2013-03-10 19:44:48 +01001834 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001835 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001836 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001837 err_code |= ERR_ALERT | ERR_FATAL;
1838 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001839 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001840
1841 proto = protocol_by_family(sk->ss_family);
1842 if (!proto || !proto->connect) {
1843 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1844 file, linenum, args[0], args[1]);
1845 err_code |= ERR_ALERT | ERR_FATAL;
1846 goto out;
1847 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001848
1849 if (port1 != port2) {
1850 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1851 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001852 err_code |= ERR_ALERT | ERR_FATAL;
1853 goto out;
1854 }
1855
Willy Tarreau2aa38802013-02-20 19:20:59 +01001856 if (!port1) {
1857 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1858 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001859 err_code |= ERR_ALERT | ERR_FATAL;
1860 goto out;
1861 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001862
Emeric Brun32da3c42010-09-23 18:39:19 +02001863 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001864 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001865 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001866 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001867
Emeric Brun32da3c42010-09-23 18:39:19 +02001868 if (strcmp(newpeer->id, localpeer) == 0) {
1869 /* Current is local peer, it define a frontend */
1870 newpeer->local = 1;
1871
1872 if (!curpeers->peers_fe) {
1873 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1874 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1875 err_code |= ERR_ALERT | ERR_ABORT;
1876 goto out;
1877 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001878
Willy Tarreau237250c2011-07-29 01:49:03 +02001879 init_new_proxy(curpeers->peers_fe);
1880 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001881 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001882 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1883 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01001884 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02001885
1886 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1887
Willy Tarreau902636f2013-03-10 19:44:48 +01001888 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1889 if (errmsg && *errmsg) {
1890 indent_msg(&errmsg, 2);
1891 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001892 }
1893 else
1894 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1895 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001896 err_code |= ERR_FATAL;
1897 goto out;
1898 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001899
1900 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001901 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001902 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1903 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02001904 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02001905 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001906 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01001907 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001908 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1909 global.maxsock += l->maxconn;
1910 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001911 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001912 else {
1913 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1914 file, linenum, args[0], args[1],
1915 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1916 err_code |= ERR_FATAL;
1917 goto out;
1918 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001919 }
1920 } /* neither "peer" nor "peers" */
1921 else if (*args[0] != 0) {
1922 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1923 err_code |= ERR_ALERT | ERR_FATAL;
1924 goto out;
1925 }
1926
1927out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001928 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001929 return err_code;
1930}
1931
Simon Horman0d16a402015-01-30 11:22:58 +09001932
1933/*
1934 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
1935 * Returns the error code, 0 if OK, or any combination of :
1936 * - ERR_ABORT: must abort ASAP
1937 * - ERR_FATAL: we can continue parsing but not start the service
1938 * - ERR_WARN: a warning has been emitted
1939 * - ERR_ALERT: an alert has been emitted
1940 * Only the two first ones can stop processing, the two others are just
1941 * indicators.
1942 */
1943int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
1944{
1945 static struct mailers *curmailers = NULL;
1946 struct mailer *newmailer = NULL;
1947 const char *err;
1948 int err_code = 0;
1949 char *errmsg = NULL;
1950
1951 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
1952 if (!*args[1]) {
1953 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
1954 err_code |= ERR_ALERT | ERR_ABORT;
1955 goto out;
1956 }
1957
1958 err = invalid_char(args[1]);
1959 if (err) {
1960 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1961 file, linenum, *err, args[0], args[1]);
1962 err_code |= ERR_ALERT | ERR_ABORT;
1963 goto out;
1964 }
1965
1966 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
1967 /*
1968 * If there are two proxies with the same name only following
1969 * combinations are allowed:
1970 */
1971 if (strcmp(curmailers->id, args[1]) == 0) {
1972 Warning("Parsing [%s:%d]: mailers '%s' has same name as another mailers (declared at %s:%d).\n",
1973 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
1974 err_code |= ERR_WARN;
1975 }
1976 }
1977
1978 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
1979 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1980 err_code |= ERR_ALERT | ERR_ABORT;
1981 goto out;
1982 }
1983
1984 curmailers->next = mailers;
1985 mailers = curmailers;
1986 curmailers->conf.file = strdup(file);
1987 curmailers->conf.line = linenum;
1988 curmailers->id = strdup(args[1]);
1989 }
1990 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
1991 struct sockaddr_storage *sk;
1992 int port1, port2;
1993 struct protocol *proto;
1994
1995 if (!*args[2]) {
1996 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1997 file, linenum, args[0]);
1998 err_code |= ERR_ALERT | ERR_FATAL;
1999 goto out;
2000 }
2001
2002 err = invalid_char(args[1]);
2003 if (err) {
2004 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2005 file, linenum, *err, args[1]);
2006 err_code |= ERR_ALERT | ERR_FATAL;
2007 goto out;
2008 }
2009
2010 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2011 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2012 err_code |= ERR_ALERT | ERR_ABORT;
2013 goto out;
2014 }
2015
2016 /* the mailers are linked backwards first */
2017 curmailers->count++;
2018 newmailer->next = curmailers->mailer_list;
2019 curmailers->mailer_list = newmailer;
2020 newmailer->mailers = curmailers;
2021 newmailer->conf.file = strdup(file);
2022 newmailer->conf.line = linenum;
2023
2024 newmailer->id = strdup(args[1]);
2025
2026 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2027 if (!sk) {
2028 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2029 err_code |= ERR_ALERT | ERR_FATAL;
2030 goto out;
2031 }
2032
2033 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002034 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2035 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002036 file, linenum, args[0], args[1]);
2037 err_code |= ERR_ALERT | ERR_FATAL;
2038 goto out;
2039 }
2040
2041 if (port1 != port2) {
2042 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2043 file, linenum, args[0], args[1], args[2]);
2044 err_code |= ERR_ALERT | ERR_FATAL;
2045 goto out;
2046 }
2047
2048 if (!port1) {
2049 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2050 file, linenum, args[0], args[1], args[2]);
2051 err_code |= ERR_ALERT | ERR_FATAL;
2052 goto out;
2053 }
2054
2055 newmailer->addr = *sk;
2056 newmailer->proto = proto;
2057 newmailer->xprt = &raw_sock;
2058 newmailer->sock_init_arg = NULL;
2059 } /* neither "mailer" nor "mailers" */
2060 else if (*args[0] != 0) {
2061 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2062 err_code |= ERR_ALERT | ERR_FATAL;
2063 goto out;
2064 }
2065
2066out:
2067 free(errmsg);
2068 return err_code;
2069}
2070
Simon Horman9dc49962015-01-30 11:22:59 +09002071static void free_email_alert(struct proxy *p)
2072{
2073 free(p->email_alert.mailers.name);
2074 p->email_alert.mailers.name = NULL;
2075 free(p->email_alert.from);
2076 p->email_alert.from = NULL;
2077 free(p->email_alert.to);
2078 p->email_alert.to = NULL;
2079 free(p->email_alert.myhostname);
2080 p->email_alert.myhostname = NULL;
2081}
2082
Willy Tarreau3842f002009-06-14 11:39:52 +02002083int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002084{
2085 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002086 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002087 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002088 int rc;
2089 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002090 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002091 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002092 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002093 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002094 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002095
Willy Tarreau977b8e42006-12-29 14:19:17 +01002096 if (!strcmp(args[0], "listen"))
2097 rc = PR_CAP_LISTEN;
2098 else if (!strcmp(args[0], "frontend"))
2099 rc = PR_CAP_FE | PR_CAP_RS;
2100 else if (!strcmp(args[0], "backend"))
2101 rc = PR_CAP_BE | PR_CAP_RS;
2102 else if (!strcmp(args[0], "ruleset"))
2103 rc = PR_CAP_RS;
2104 else
2105 rc = PR_CAP_NONE;
2106
2107 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002108 struct ebpt_node *node;
2109
Willy Tarreaubaaee002006-06-26 02:48:02 +02002110 if (!*args[1]) {
2111 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2112 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2113 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002114 err_code |= ERR_ALERT | ERR_ABORT;
2115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002116 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002117
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002118 err = invalid_char(args[1]);
2119 if (err) {
2120 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2121 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002122 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002123 }
2124
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002125 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
2126 curproxy = container_of(node, struct proxy, conf.by_name);
2127
2128 if (strcmp(curproxy->id, args[1]) != 0)
2129 break;
2130
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002131 /*
2132 * If there are two proxies with the same name only following
2133 * combinations are allowed:
2134 *
2135 * listen backend frontend ruleset
2136 * listen - - - -
2137 * backend - - OK -
2138 * frontend - OK - -
2139 * ruleset - - - -
2140 */
2141
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002142 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
2143 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02002144 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
2145 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2146 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02002147 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002148 }
2149 }
2150
Willy Tarreaubaaee002006-06-26 02:48:02 +02002151 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2152 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002153 err_code |= ERR_ALERT | ERR_ABORT;
2154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002155 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002156
Willy Tarreau97cb7802010-01-03 20:23:58 +01002157 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002158 curproxy->next = proxy;
2159 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002160 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2161 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002162 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002163 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002164 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002165 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002166
2167 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002168 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002169 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02002170
Willy Tarreau4348fad2012-09-20 16:48:07 +02002171 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2172
Willy Tarreau902636f2013-03-10 19:44:48 +01002173 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2174 if (errmsg && *errmsg) {
2175 indent_msg(&errmsg, 2);
2176 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002177 }
2178 else
2179 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2180 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002181 err_code |= ERR_FATAL;
2182 goto out;
2183 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002184
Willy Tarreau4348fad2012-09-20 16:48:07 +02002185 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002186 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002187 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002188 }
2189
2190 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002191 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002192 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002193
Willy Tarreaubaaee002006-06-26 02:48:02 +02002194 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002195 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002196 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002197 curproxy->no_options = defproxy.no_options;
2198 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002199 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002200 curproxy->except_net = defproxy.except_net;
2201 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002202 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002203 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002205 if (defproxy.fwdfor_hdr_len) {
2206 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2207 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2208 }
2209
Willy Tarreaub86db342009-11-30 11:50:16 +01002210 if (defproxy.orgto_hdr_len) {
2211 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2212 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2213 }
2214
Mark Lamourinec2247f02012-01-04 13:02:01 -05002215 if (defproxy.server_id_hdr_len) {
2216 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2217 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2218 }
2219
Willy Tarreau977b8e42006-12-29 14:19:17 +01002220 if (curproxy->cap & PR_CAP_FE) {
2221 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002222 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002223 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002224
2225 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002226 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2227 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002228
2229 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2230 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002231
Willy Tarreau977b8e42006-12-29 14:19:17 +01002232 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002233 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002234 curproxy->fullconn = defproxy.fullconn;
2235 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002236 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002237
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002238 if (defproxy.check_req) {
2239 curproxy->check_req = calloc(1, defproxy.check_len);
2240 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2241 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002242 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002243
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002244 if (defproxy.expect_str) {
2245 curproxy->expect_str = strdup(defproxy.expect_str);
2246 if (defproxy.expect_regex) {
2247 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002248 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2249 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002250 }
2251 }
2252
Willy Tarreau67402132012-05-31 20:40:20 +02002253 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002254 if (defproxy.cookie_name)
2255 curproxy->cookie_name = strdup(defproxy.cookie_name);
2256 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002257 if (defproxy.cookie_domain)
2258 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002259
Willy Tarreau31936852010-10-06 16:59:56 +02002260 if (defproxy.cookie_maxidle)
2261 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2262
2263 if (defproxy.cookie_maxlife)
2264 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2265
Emeric Brun647caf12009-06-30 17:57:00 +02002266 if (defproxy.rdp_cookie_name)
2267 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2268 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2269
Willy Tarreau01732802007-11-01 22:48:15 +01002270 if (defproxy.url_param_name)
2271 curproxy->url_param_name = strdup(defproxy.url_param_name);
2272 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002273
Benoitaffb4812009-03-25 13:02:10 +01002274 if (defproxy.hh_name)
2275 curproxy->hh_name = strdup(defproxy.hh_name);
2276 curproxy->hh_len = defproxy.hh_len;
2277 curproxy->hh_match_domain = defproxy.hh_match_domain;
2278
Willy Tarreauef9a3602012-12-08 22:29:20 +01002279 if (defproxy.conn_src.iface_name)
2280 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2281 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002282 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002283#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002284 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002285#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002286 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002287
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002288 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002289 if (defproxy.capture_name)
2290 curproxy->capture_name = strdup(defproxy.capture_name);
2291 curproxy->capture_namelen = defproxy.capture_namelen;
2292 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002293 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294
Willy Tarreau977b8e42006-12-29 14:19:17 +01002295 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002296 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002297 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002298 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002299 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002300 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002301 curproxy->mon_net = defproxy.mon_net;
2302 curproxy->mon_mask = defproxy.mon_mask;
2303 if (defproxy.monitor_uri)
2304 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2305 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002306 if (defproxy.defbe.name)
2307 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002308
2309 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002310 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2311 if (curproxy->conf.logformat_string &&
2312 curproxy->conf.logformat_string != default_http_log_format &&
2313 curproxy->conf.logformat_string != default_tcp_log_format &&
2314 curproxy->conf.logformat_string != clf_http_log_format)
2315 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2316
2317 if (defproxy.conf.lfs_file) {
2318 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2319 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2320 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002321 }
2322
2323 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002324 curproxy->timeout.connect = defproxy.timeout.connect;
2325 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002326 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002327 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002328 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002329 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002330 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002331 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002332 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002333 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002334 }
2335
Willy Tarreaubaaee002006-06-26 02:48:02 +02002336 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002337 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002338
2339 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002340 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002341 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002342 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002343 LIST_INIT(&node->list);
2344 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2345 }
2346
Willy Tarreau62a61232013-04-12 18:13:46 +02002347 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2348 if (curproxy->conf.uniqueid_format_string)
2349 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2350
Willy Tarreau094af4e2015-01-07 15:03:42 +01002351 if (defproxy.log_tag)
2352 curproxy->log_tag = strdup(defproxy.log_tag);
2353
Willy Tarreau62a61232013-04-12 18:13:46 +02002354 if (defproxy.conf.uif_file) {
2355 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2356 curproxy->conf.uif_line = defproxy.conf.uif_line;
2357 }
William Lallemanda73203e2012-03-12 12:48:57 +01002358
2359 /* copy default header unique id */
2360 if (defproxy.header_unique_id)
2361 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2362
William Lallemand82fe75c2012-10-23 10:25:10 +02002363 /* default compression options */
2364 if (defproxy.comp != NULL) {
2365 curproxy->comp = calloc(1, sizeof(struct comp));
2366 curproxy->comp->algos = defproxy.comp->algos;
2367 curproxy->comp->types = defproxy.comp->types;
2368 }
2369
Willy Tarreaubaaee002006-06-26 02:48:02 +02002370 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002371 curproxy->conf.used_listener_id = EB_ROOT;
2372 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002373
Simon Horman98637e52014-06-20 12:30:16 +09002374 if (defproxy.check_path)
2375 curproxy->check_path = strdup(defproxy.check_path);
2376 if (defproxy.check_command)
2377 curproxy->check_command = strdup(defproxy.check_command);
2378
Simon Horman9dc49962015-01-30 11:22:59 +09002379 if (defproxy.email_alert.mailers.name)
2380 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2381 if (defproxy.email_alert.from)
2382 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2383 if (defproxy.email_alert.to)
2384 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2385 if (defproxy.email_alert.myhostname)
2386 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002387 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002388
Willy Tarreau93893792009-07-23 13:19:11 +02002389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390 }
2391 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2392 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002393 /* FIXME-20070101: we should do this too at the end of the
2394 * config parsing to free all default values.
2395 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002396 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002397 free(defproxy.check_command);
2398 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002399 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002400 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002401 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002402 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002403 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002404 free(defproxy.capture_name);
2405 free(defproxy.monitor_uri);
2406 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002407 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002408 free(defproxy.fwdfor_hdr_name);
2409 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002410 free(defproxy.orgto_hdr_name);
2411 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002412 free(defproxy.server_id_hdr_name);
2413 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002414 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002415 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002416 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002417 free(defproxy.expect_regex);
2418 defproxy.expect_regex = NULL;
2419 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002420
Willy Tarreau62a61232013-04-12 18:13:46 +02002421 if (defproxy.conf.logformat_string != default_http_log_format &&
2422 defproxy.conf.logformat_string != default_tcp_log_format &&
2423 defproxy.conf.logformat_string != clf_http_log_format)
2424 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002425
Willy Tarreau62a61232013-04-12 18:13:46 +02002426 free(defproxy.conf.uniqueid_format_string);
2427 free(defproxy.conf.lfs_file);
2428 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002429 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002430 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002431
Willy Tarreaua534fea2008-08-03 12:19:50 +02002432 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002433 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002434
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 /* we cannot free uri_auth because it might already be used */
2436 init_default_instance();
2437 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002438 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2439 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002440 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 }
2443 else if (curproxy == NULL) {
2444 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002445 err_code |= ERR_ALERT | ERR_FATAL;
2446 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002447 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002448
2449 /* update the current file and line being parsed */
2450 curproxy->conf.args.file = curproxy->conf.file;
2451 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002452
2453 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002454 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2455 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2456 if (err_code & ERR_FATAL)
2457 goto out;
2458 }
2459 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002460 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002461 int cur_arg;
2462
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 if (curproxy == &defproxy) {
2464 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002465 err_code |= ERR_ALERT | ERR_FATAL;
2466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002468 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002469 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002470
Willy Tarreau24709282013-03-10 21:32:12 +01002471 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002472 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002474 err_code |= ERR_ALERT | ERR_FATAL;
2475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002476 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002477
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002478 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002479
2480 /* use default settings for unix sockets */
2481 bind_conf->ux.uid = global.unix_bind.ux.uid;
2482 bind_conf->ux.gid = global.unix_bind.ux.gid;
2483 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002484
2485 /* NOTE: the following line might create several listeners if there
2486 * are comma-separated IPs or port ranges. So all further processing
2487 * will have to be applied to all listeners created after last_listen.
2488 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002489 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2490 if (errmsg && *errmsg) {
2491 indent_msg(&errmsg, 2);
2492 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002493 }
2494 else
2495 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2496 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
2499 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002500
Willy Tarreau4348fad2012-09-20 16:48:07 +02002501 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2502 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002503 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002504 }
2505
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002506 cur_arg = 2;
2507 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002508 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002509 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002510 char *err;
2511
Willy Tarreau26982662012-09-12 23:17:10 +02002512 kw = bind_find_kw(args[cur_arg]);
2513 if (kw) {
2514 char *err = NULL;
2515 int code;
2516
2517 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002518 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2519 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002520 cur_arg += 1 + kw->skip ;
2521 err_code |= ERR_ALERT | ERR_FATAL;
2522 goto out;
2523 }
2524
Willy Tarreau4348fad2012-09-20 16:48:07 +02002525 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002526 err_code |= code;
2527
2528 if (code) {
2529 if (err && *err) {
2530 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002531 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002532 }
2533 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002534 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2535 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002536 if (code & ERR_FATAL) {
2537 free(err);
2538 cur_arg += 1 + kw->skip;
2539 goto out;
2540 }
2541 }
2542 free(err);
2543 cur_arg += 1 + kw->skip;
2544 continue;
2545 }
2546
Willy Tarreau8638f482012-09-18 18:01:17 +02002547 err = NULL;
2548 if (!bind_dumped) {
2549 bind_dump_kws(&err);
2550 indent_msg(&err, 4);
2551 bind_dumped = 1;
2552 }
2553
2554 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2555 file, linenum, args[0], args[1], args[cur_arg],
2556 err ? " Registered keywords :" : "", err ? err : "");
2557 free(err);
2558
Willy Tarreau93893792009-07-23 13:19:11 +02002559 err_code |= ERR_ALERT | ERR_FATAL;
2560 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002561 }
Willy Tarreau93893792009-07-23 13:19:11 +02002562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002563 }
2564 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002565 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2567 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002568 err_code |= ERR_ALERT | ERR_FATAL;
2569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002571 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002572 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002573
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 /* flush useless bits */
2575 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002578 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002579 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002580 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002581
Willy Tarreau1c47f852006-07-09 08:22:27 +02002582 if (!*args[1]) {
2583 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2584 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002585 err_code |= ERR_ALERT | ERR_FATAL;
2586 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002587 }
2588
Willy Tarreaua534fea2008-08-03 12:19:50 +02002589 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002590 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002591 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002592 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002593 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2594
Willy Tarreau93893792009-07-23 13:19:11 +02002595 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002596 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2598 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2599 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2600 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2601 else {
2602 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 }
2606 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002607 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002608 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002609
2610 if (curproxy == &defproxy) {
2611 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2612 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002613 err_code |= ERR_ALERT | ERR_FATAL;
2614 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002615 }
2616
2617 if (!*args[1]) {
2618 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2619 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002620 err_code |= ERR_ALERT | ERR_FATAL;
2621 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002622 }
2623
2624 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002625 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002626
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002627 if (curproxy->uuid <= 0) {
2628 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002629 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002632 }
2633
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002634 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2635 if (node) {
2636 struct proxy *target = container_of(node, struct proxy, conf.id);
2637 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2638 file, linenum, proxy_type_str(curproxy), curproxy->id,
2639 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2640 err_code |= ERR_ALERT | ERR_FATAL;
2641 goto out;
2642 }
2643 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002644 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002645 else if (!strcmp(args[0], "description")) {
2646 int i, len=0;
2647 char *d;
2648
Cyril Bonté99ed3272010-01-24 23:29:44 +01002649 if (curproxy == &defproxy) {
2650 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2651 file, linenum, args[0]);
2652 err_code |= ERR_ALERT | ERR_FATAL;
2653 goto out;
2654 }
2655
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002656 if (!*args[1]) {
2657 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2658 file, linenum, args[0]);
2659 return -1;
2660 }
2661
Willy Tarreau348acfe2014-04-14 15:00:39 +02002662 for (i = 1; *args[i]; i++)
2663 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002664
2665 d = (char *)calloc(1, len);
2666 curproxy->desc = d;
2667
Willy Tarreau348acfe2014-04-14 15:00:39 +02002668 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2669 for (i = 2; *args[i]; i++)
2670 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002671
2672 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002673 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2674 curproxy->state = PR_STSTOPPED;
2675 }
2676 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2677 curproxy->state = PR_STNEW;
2678 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002679 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2680 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002681 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002682
2683 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002684 unsigned int low, high;
2685
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002686 if (strcmp(args[cur_arg], "all") == 0) {
2687 set = 0;
2688 break;
2689 }
2690 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002691 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002692 }
2693 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002694 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002695 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002696 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002697 char *dash = strchr(args[cur_arg], '-');
2698
2699 low = high = str2uic(args[cur_arg]);
2700 if (dash)
2701 high = str2uic(dash + 1);
2702
2703 if (high < low) {
2704 unsigned int swap = low;
2705 low = high;
2706 high = swap;
2707 }
2708
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002709 if (low < 1 || high > LONGBITS) {
2710 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2711 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002712 err_code |= ERR_ALERT | ERR_FATAL;
2713 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002714 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002715 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002716 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002717 }
2718 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002719 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2720 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002721 err_code |= ERR_ALERT | ERR_FATAL;
2722 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002723 }
2724 cur_arg++;
2725 }
2726 curproxy->bind_proc = set;
2727 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002728 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002729 if (curproxy == &defproxy) {
2730 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002731 err_code |= ERR_ALERT | ERR_FATAL;
2732 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002733 }
2734
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002735 err = invalid_char(args[1]);
2736 if (err) {
2737 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2738 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002739 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002740 }
2741
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002742 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002743 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2744 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002747 }
2748 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002749 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2750 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002751
Willy Tarreau977b8e42006-12-29 14:19:17 +01002752 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002753 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002754
Willy Tarreaubaaee002006-06-26 02:48:02 +02002755 if (*(args[1]) == 0) {
2756 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2757 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002760 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002761
Willy Tarreau67402132012-05-31 20:40:20 +02002762 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002763 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002764 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002765 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002766 curproxy->cookie_name = strdup(args[1]);
2767 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002768
Willy Tarreaubaaee002006-06-26 02:48:02 +02002769 cur_arg = 2;
2770 while (*(args[cur_arg])) {
2771 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002772 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002773 }
2774 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002775 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002776 }
2777 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002778 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002779 }
2780 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002781 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782 }
2783 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002784 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002785 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002786 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002787 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002788 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002789 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002790 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002791 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002792 else if (!strcmp(args[cur_arg], "httponly")) {
2793 curproxy->ck_opts |= PR_CK_HTTPONLY;
2794 }
2795 else if (!strcmp(args[cur_arg], "secure")) {
2796 curproxy->ck_opts |= PR_CK_SECURE;
2797 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002798 else if (!strcmp(args[cur_arg], "domain")) {
2799 if (!*args[cur_arg + 1]) {
2800 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2801 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002802 err_code |= ERR_ALERT | ERR_FATAL;
2803 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002804 }
2805
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002806 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002807 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002808 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2809 " dots nor does not start with a dot."
2810 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002811 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002812 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002813 }
2814
2815 err = invalid_domainchar(args[cur_arg + 1]);
2816 if (err) {
2817 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2818 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002819 err_code |= ERR_ALERT | ERR_FATAL;
2820 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002821 }
2822
Willy Tarreau68a897b2009-12-03 23:28:34 +01002823 if (!curproxy->cookie_domain) {
2824 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2825 } else {
2826 /* one domain was already specified, add another one by
2827 * building the string which will be returned along with
2828 * the cookie.
2829 */
2830 char *new_ptr;
2831 int new_len = strlen(curproxy->cookie_domain) +
2832 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2833 new_ptr = malloc(new_len);
2834 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2835 free(curproxy->cookie_domain);
2836 curproxy->cookie_domain = new_ptr;
2837 }
Willy Tarreau31936852010-10-06 16:59:56 +02002838 cur_arg++;
2839 }
2840 else if (!strcmp(args[cur_arg], "maxidle")) {
2841 unsigned int maxidle;
2842 const char *res;
2843
2844 if (!*args[cur_arg + 1]) {
2845 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2846 file, linenum, args[cur_arg]);
2847 err_code |= ERR_ALERT | ERR_FATAL;
2848 goto out;
2849 }
2850
2851 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2852 if (res) {
2853 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2854 file, linenum, *res, args[cur_arg]);
2855 err_code |= ERR_ALERT | ERR_FATAL;
2856 goto out;
2857 }
2858 curproxy->cookie_maxidle = maxidle;
2859 cur_arg++;
2860 }
2861 else if (!strcmp(args[cur_arg], "maxlife")) {
2862 unsigned int maxlife;
2863 const char *res;
2864
2865 if (!*args[cur_arg + 1]) {
2866 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2867 file, linenum, args[cur_arg]);
2868 err_code |= ERR_ALERT | ERR_FATAL;
2869 goto out;
2870 }
2871
2872 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2873 if (res) {
2874 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2875 file, linenum, *res, args[cur_arg]);
2876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
2878 }
2879 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002880 cur_arg++;
2881 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002882 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002883 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 +02002884 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002885 err_code |= ERR_ALERT | ERR_FATAL;
2886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002887 }
2888 cur_arg++;
2889 }
Willy Tarreau67402132012-05-31 20:40:20 +02002890 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002891 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2892 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002893 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002894 }
2895
Willy Tarreau67402132012-05-31 20:40:20 +02002896 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2898 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002899 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002900 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002901
Willy Tarreau67402132012-05-31 20:40:20 +02002902 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002903 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2904 file, linenum);
2905 err_code |= ERR_ALERT | ERR_FATAL;
2906 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002907 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09002908 else if (!strcmp(args[0], "email-alert")) {
2909 if (*(args[1]) == 0) {
2910 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2911 file, linenum, args[0]);
2912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
2914 }
2915
2916 if (!strcmp(args[1], "from")) {
2917 if (*(args[1]) == 0) {
2918 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2919 file, linenum, args[1]);
2920 err_code |= ERR_ALERT | ERR_FATAL;
2921 goto out;
2922 }
2923 free(curproxy->email_alert.from);
2924 curproxy->email_alert.from = strdup(args[2]);
2925 }
2926 else if (!strcmp(args[1], "mailers")) {
2927 if (*(args[1]) == 0) {
2928 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2929 file, linenum, args[1]);
2930 err_code |= ERR_ALERT | ERR_FATAL;
2931 goto out;
2932 }
2933 free(curproxy->email_alert.mailers.name);
2934 curproxy->email_alert.mailers.name = strdup(args[2]);
2935 }
2936 else if (!strcmp(args[1], "myhostname")) {
2937 if (*(args[1]) == 0) {
2938 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2939 file, linenum, args[1]);
2940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
2942 }
2943 free(curproxy->email_alert.myhostname);
2944 curproxy->email_alert.myhostname = strdup(args[2]);
2945 }
Simon Horman64e34162015-02-06 11:11:57 +09002946 else if (!strcmp(args[1], "level")) {
2947 curproxy->email_alert.level = get_log_level(args[2]);
2948 if (curproxy->email_alert.level < 0) {
2949 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
2950 file, linenum, args[1], args[2]);
2951 err_code |= ERR_ALERT | ERR_FATAL;
2952 goto out;
2953 }
2954 }
Simon Horman9dc49962015-01-30 11:22:59 +09002955 else if (!strcmp(args[1], "to")) {
2956 if (*(args[1]) == 0) {
2957 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2958 file, linenum, args[1]);
2959 err_code |= ERR_ALERT | ERR_FATAL;
2960 goto out;
2961 }
2962 free(curproxy->email_alert.to);
2963 curproxy->email_alert.to = strdup(args[2]);
2964 }
2965 else {
2966 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
2967 file, linenum, args[1]);
2968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
2970 }
Simon Horman64e34162015-02-06 11:11:57 +09002971 /* Indicate that the email_alert is at least partially configured */
2972 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09002973 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09002974 else if (!strcmp(args[0], "external-check")) {
2975 if (*(args[1]) == 0) {
2976 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2977 file, linenum, args[0]);
2978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
2980 }
2981
2982 if (!strcmp(args[1], "command")) {
2983 if (*(args[1]) == 0) {
2984 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2985 file, linenum, args[1]);
2986 err_code |= ERR_ALERT | ERR_FATAL;
2987 goto out;
2988 }
2989 free(curproxy->check_command);
2990 curproxy->check_command = strdup(args[2]);
2991 }
2992 else if (!strcmp(args[1], "path")) {
2993 if (*(args[1]) == 0) {
2994 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2995 file, linenum, args[1]);
2996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
2998 }
2999 free(curproxy->check_path);
3000 curproxy->check_path = strdup(args[2]);
3001 }
3002 else {
3003 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3004 file, linenum, args[1]);
3005 err_code |= ERR_ALERT | ERR_FATAL;
3006 goto out;
3007 }
3008 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003009 else if (!strcmp(args[0], "persist")) { /* persist */
3010 if (*(args[1]) == 0) {
3011 Alert("parsing [%s:%d] : missing persist method.\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 if (!strncmp(args[1], "rdp-cookie", 10)) {
3018 curproxy->options2 |= PR_O2_RDPC_PRST;
3019
Emeric Brunb982a3d2010-01-04 15:45:53 +01003020 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003021 const char *beg, *end;
3022
3023 beg = args[1] + 11;
3024 end = strchr(beg, ')');
3025
3026 if (!end || end == beg) {
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 free(curproxy->rdp_cookie_name);
3034 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3035 curproxy->rdp_cookie_len = end-beg;
3036 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003037 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003038 free(curproxy->rdp_cookie_name);
3039 curproxy->rdp_cookie_name = strdup("msts");
3040 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3041 }
3042 else { /* syntax */
3043 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3044 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003047 }
3048 }
3049 else {
3050 Alert("parsing [%s:%d] : unknown persist method.\n",
3051 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003052 err_code |= ERR_ALERT | ERR_FATAL;
3053 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003054 }
3055 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003056 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003057 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003059 if (curproxy == &defproxy) {
3060 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
3063 }
3064
Willy Tarreau977b8e42006-12-29 14:19:17 +01003065 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003066 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003067
Willy Tarreaubaaee002006-06-26 02:48:02 +02003068 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003069 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003073 }
3074 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003075 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003076 curproxy->appsession_name = strdup(args[1]);
3077 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3078 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003079 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3080 if (err) {
3081 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3082 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003085 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003086 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003087
Willy Tarreau51041c72007-09-09 21:56:53 +02003088 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3089 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003090 err_code |= ERR_ALERT | ERR_ABORT;
3091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003092 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003093
3094 cur_arg = 6;
3095 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003096 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3097 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003098 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003099 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003100 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003101 } else if (!strcmp(args[cur_arg], "prefix")) {
3102 curproxy->options2 |= PR_O2_AS_PFX;
3103 } else if (!strcmp(args[cur_arg], "mode")) {
3104 if (!*args[cur_arg + 1]) {
3105 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3106 file, linenum, args[0], args[cur_arg]);
3107 err_code |= ERR_ALERT | ERR_FATAL;
3108 goto out;
3109 }
3110
3111 cur_arg++;
3112 if (!strcmp(args[cur_arg], "query-string")) {
3113 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3114 curproxy->options2 |= PR_O2_AS_M_QS;
3115 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3116 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3117 curproxy->options2 |= PR_O2_AS_M_PP;
3118 } else {
3119 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
3122 }
3123 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003124 cur_arg++;
3125 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126 } /* Url App Session */
3127 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003128 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003130
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003132 if (curproxy == &defproxy) {
3133 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3134 err_code |= ERR_ALERT | ERR_FATAL;
3135 goto out;
3136 }
3137
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138 if (*(args[4]) == 0) {
3139 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3140 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003141 err_code |= ERR_ALERT | ERR_FATAL;
3142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003143 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003144 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145 curproxy->capture_name = strdup(args[2]);
3146 curproxy->capture_namelen = strlen(curproxy->capture_name);
3147 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 curproxy->to_log |= LW_COOKIE;
3149 }
3150 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3151 struct cap_hdr *hdr;
3152
3153 if (curproxy == &defproxy) {
3154 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 +02003155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003157 }
3158
3159 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3160 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3161 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003162 err_code |= ERR_ALERT | ERR_FATAL;
3163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003164 }
3165
3166 hdr = calloc(sizeof(struct cap_hdr), 1);
3167 hdr->next = curproxy->req_cap;
3168 hdr->name = strdup(args[3]);
3169 hdr->namelen = strlen(args[3]);
3170 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003171 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003172 hdr->index = curproxy->nb_req_cap++;
3173 curproxy->req_cap = hdr;
3174 curproxy->to_log |= LW_REQHDR;
3175 }
3176 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3177 struct cap_hdr *hdr;
3178
3179 if (curproxy == &defproxy) {
3180 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 +02003181 err_code |= ERR_ALERT | ERR_FATAL;
3182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 }
3184
3185 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3186 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3187 file, linenum, args[0], args[1]);
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 hdr = calloc(sizeof(struct cap_hdr), 1);
3192 hdr->next = curproxy->rsp_cap;
3193 hdr->name = strdup(args[3]);
3194 hdr->namelen = strlen(args[3]);
3195 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003196 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003197 hdr->index = curproxy->nb_rsp_cap++;
3198 curproxy->rsp_cap = hdr;
3199 curproxy->to_log |= LW_RSPHDR;
3200 }
3201 else {
3202 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3203 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003206 }
3207 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003209 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003210 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003211
Willy Tarreaubaaee002006-06-26 02:48:02 +02003212 if (*(args[1]) == 0) {
3213 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3214 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 }
3218 curproxy->conn_retries = atol(args[1]);
3219 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003220 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003221 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003222
3223 if (curproxy == &defproxy) {
3224 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3225 err_code |= ERR_ALERT | ERR_FATAL;
3226 goto out;
3227 }
3228
Willy Tarreau20b0de52012-12-24 15:45:22 +01003229 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3230 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3231 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3232 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003233 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003234 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3235 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 +01003236 file, linenum, args[0]);
3237 err_code |= ERR_WARN;
3238 }
3239
Willy Tarreauff011f22011-01-06 17:51:27 +01003240 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003241
Willy Tarreauff011f22011-01-06 17:51:27 +01003242 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003243 err_code |= ERR_ALERT | ERR_ABORT;
3244 goto out;
3245 }
3246
Willy Tarreau5002f572014-04-23 01:32:02 +02003247 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003248 err_code |= warnif_cond_conflicts(rule->cond,
3249 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3250 file, linenum);
3251
Willy Tarreauff011f22011-01-06 17:51:27 +01003252 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003253 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003254 else if (!strcmp(args[0], "http-response")) { /* response access control */
3255 struct http_res_rule *rule;
3256
3257 if (curproxy == &defproxy) {
3258 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3259 err_code |= ERR_ALERT | ERR_FATAL;
3260 goto out;
3261 }
3262
3263 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3264 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3265 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3266 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3267 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3268 file, linenum, args[0]);
3269 err_code |= ERR_WARN;
3270 }
3271
3272 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3273
3274 if (!rule) {
3275 err_code |= ERR_ALERT | ERR_ABORT;
3276 goto out;
3277 }
3278
3279 err_code |= warnif_cond_conflicts(rule->cond,
3280 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3281 file, linenum);
3282
3283 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3284 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003285 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3286 /* set the header name and length into the proxy structure */
3287 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3288 err_code |= ERR_WARN;
3289
3290 if (!*args[1]) {
3291 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3292 file, linenum, args[0]);
3293 err_code |= ERR_ALERT | ERR_FATAL;
3294 goto out;
3295 }
3296
3297 /* set the desired header name */
3298 free(curproxy->server_id_hdr_name);
3299 curproxy->server_id_hdr_name = strdup(args[1]);
3300 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3301 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003302 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003303 struct http_req_rule *rule;
3304
Willy Tarreaub099aca2008-10-12 17:26:37 +02003305 if (curproxy == &defproxy) {
3306 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003307 err_code |= ERR_ALERT | ERR_FATAL;
3308 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003309 }
3310
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003311 /* emulate "block" using "http-request block". Since these rules are supposed to
3312 * be processed before all http-request rules, we put them into their own list
3313 * and will insert them at the end.
3314 */
3315 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3316 if (!rule) {
3317 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003318 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003319 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003320 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3321 err_code |= warnif_cond_conflicts(rule->cond,
3322 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3323 file, linenum);
3324 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003325
3326 if (!already_warned(WARN_BLOCK_DEPRECATED))
3327 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]);
3328
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003329 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003330 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003331 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003332
Cyril Bonté99ed3272010-01-24 23:29:44 +01003333 if (curproxy == &defproxy) {
3334 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3335 err_code |= ERR_ALERT | ERR_FATAL;
3336 goto out;
3337 }
3338
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003339 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003340 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3341 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003342 err_code |= ERR_ALERT | ERR_FATAL;
3343 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003344 }
3345
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003346 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003347 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003348 err_code |= warnif_cond_conflicts(rule->cond,
3349 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3350 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003351 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003352 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003353 struct switching_rule *rule;
3354
Willy Tarreaub099aca2008-10-12 17:26:37 +02003355 if (curproxy == &defproxy) {
3356 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003359 }
3360
Willy Tarreau55ea7572007-06-17 19:56:27 +02003361 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003362 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003363
3364 if (*(args[1]) == 0) {
3365 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003366 err_code |= ERR_ALERT | ERR_FATAL;
3367 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003368 }
3369
Willy Tarreauf51658d2014-04-23 01:21:56 +02003370 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3371 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3372 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3373 file, linenum, errmsg);
3374 err_code |= ERR_ALERT | ERR_FATAL;
3375 goto out;
3376 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003377
Willy Tarreauf51658d2014-04-23 01:21:56 +02003378 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003379 }
3380
3381 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3382 rule->cond = cond;
3383 rule->be.name = strdup(args[1]);
3384 LIST_INIT(&rule->list);
3385 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3386 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003387 else if (strcmp(args[0], "use-server") == 0) {
3388 struct server_rule *rule;
3389
3390 if (curproxy == &defproxy) {
3391 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3392 err_code |= ERR_ALERT | ERR_FATAL;
3393 goto out;
3394 }
3395
3396 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3397 err_code |= ERR_WARN;
3398
3399 if (*(args[1]) == 0) {
3400 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3401 err_code |= ERR_ALERT | ERR_FATAL;
3402 goto out;
3403 }
3404
3405 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3406 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3407 file, linenum, args[0]);
3408 err_code |= ERR_ALERT | ERR_FATAL;
3409 goto out;
3410 }
3411
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003412 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3413 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3414 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003415 err_code |= ERR_ALERT | ERR_FATAL;
3416 goto out;
3417 }
3418
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003419 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003420
3421 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3422 rule->cond = cond;
3423 rule->srv.name = strdup(args[1]);
3424 LIST_INIT(&rule->list);
3425 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3426 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3427 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003428 else if ((!strcmp(args[0], "force-persist")) ||
3429 (!strcmp(args[0], "ignore-persist"))) {
3430 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003431
3432 if (curproxy == &defproxy) {
3433 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3434 err_code |= ERR_ALERT | ERR_FATAL;
3435 goto out;
3436 }
3437
3438 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3439 err_code |= ERR_WARN;
3440
Willy Tarreauef6494c2010-01-28 17:12:36 +01003441 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003442 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3443 file, linenum, args[0]);
3444 err_code |= ERR_ALERT | ERR_FATAL;
3445 goto out;
3446 }
3447
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003448 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3449 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3450 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003451 err_code |= ERR_ALERT | ERR_FATAL;
3452 goto out;
3453 }
3454
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003455 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3456 * where force-persist is applied.
3457 */
3458 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003459
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003460 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003461 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003462 if (!strcmp(args[0], "force-persist")) {
3463 rule->type = PERSIST_TYPE_FORCE;
3464 } else {
3465 rule->type = PERSIST_TYPE_IGNORE;
3466 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003467 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003468 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003469 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003470 else if (!strcmp(args[0], "stick-table")) {
3471 int myidx = 1;
3472
Emeric Brun32da3c42010-09-23 18:39:19 +02003473 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003474 curproxy->table.type = (unsigned int)-1;
3475 while (*args[myidx]) {
3476 const char *err;
3477
3478 if (strcmp(args[myidx], "size") == 0) {
3479 myidx++;
3480 if (!*(args[myidx])) {
3481 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3482 file, linenum, args[myidx-1]);
3483 err_code |= ERR_ALERT | ERR_FATAL;
3484 goto out;
3485 }
3486 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3487 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3488 file, linenum, *err, args[myidx-1]);
3489 err_code |= ERR_ALERT | ERR_FATAL;
3490 goto out;
3491 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003492 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003493 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003494 else if (strcmp(args[myidx], "peers") == 0) {
3495 myidx++;
Godbach50523162013-12-11 19:48:57 +08003496 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003497 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3498 file, linenum, args[myidx-1]);
3499 err_code |= ERR_ALERT | ERR_FATAL;
3500 goto out;
Godbach50523162013-12-11 19:48:57 +08003501 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003502 curproxy->table.peers.name = strdup(args[myidx++]);
3503 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003504 else if (strcmp(args[myidx], "expire") == 0) {
3505 myidx++;
3506 if (!*(args[myidx])) {
3507 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3508 file, linenum, args[myidx-1]);
3509 err_code |= ERR_ALERT | ERR_FATAL;
3510 goto out;
3511 }
3512 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3513 if (err) {
3514 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3515 file, linenum, *err, args[myidx-1]);
3516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
3518 }
3519 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003520 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003521 }
3522 else if (strcmp(args[myidx], "nopurge") == 0) {
3523 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003524 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003525 }
3526 else if (strcmp(args[myidx], "type") == 0) {
3527 myidx++;
3528 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3529 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3530 file, linenum, args[myidx]);
3531 err_code |= ERR_ALERT | ERR_FATAL;
3532 goto out;
3533 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003534 /* myidx already points to next arg */
3535 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003536 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003537 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003538 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003539
3540 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003541 nw = args[myidx];
3542 while (*nw) {
3543 /* the "store" keyword supports a comma-separated list */
3544 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003545 sa = NULL; /* store arg */
3546 while (*nw && *nw != ',') {
3547 if (*nw == '(') {
3548 *nw = 0;
3549 sa = ++nw;
3550 while (*nw != ')') {
3551 if (!*nw) {
3552 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3553 file, linenum, args[0], cw);
3554 err_code |= ERR_ALERT | ERR_FATAL;
3555 goto out;
3556 }
3557 nw++;
3558 }
3559 *nw = '\0';
3560 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003561 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003562 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003563 if (*nw)
3564 *nw++ = '\0';
3565 type = stktable_get_data_type(cw);
3566 if (type < 0) {
3567 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3568 file, linenum, args[0], cw);
3569 err_code |= ERR_ALERT | ERR_FATAL;
3570 goto out;
3571 }
Willy Tarreauac782882010-06-20 10:41:54 +02003572
3573 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3574 switch (err) {
3575 case PE_NONE: break;
3576 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003577 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3578 file, linenum, args[0], cw);
3579 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003580 break;
3581
3582 case PE_ARG_MISSING:
3583 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3584 file, linenum, args[0], cw);
3585 err_code |= ERR_ALERT | ERR_FATAL;
3586 goto out;
3587
3588 case PE_ARG_NOT_USED:
3589 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3590 file, linenum, args[0], cw);
3591 err_code |= ERR_ALERT | ERR_FATAL;
3592 goto out;
3593
3594 default:
3595 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3596 file, linenum, args[0], cw);
3597 err_code |= ERR_ALERT | ERR_FATAL;
3598 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003599 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003600 }
3601 myidx++;
3602 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003603 else {
3604 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3605 file, linenum, args[myidx]);
3606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003608 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003609 }
3610
3611 if (!curproxy->table.size) {
3612 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3613 file, linenum);
3614 err_code |= ERR_ALERT | ERR_FATAL;
3615 goto out;
3616 }
3617
3618 if (curproxy->table.type == (unsigned int)-1) {
3619 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3620 file, linenum);
3621 err_code |= ERR_ALERT | ERR_FATAL;
3622 goto out;
3623 }
3624 }
3625 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003626 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003627 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003628 int myidx = 0;
3629 const char *name = NULL;
3630 int flags;
3631
3632 if (curproxy == &defproxy) {
3633 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3634 err_code |= ERR_ALERT | ERR_FATAL;
3635 goto out;
3636 }
3637
3638 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3639 err_code |= ERR_WARN;
3640 goto out;
3641 }
3642
3643 myidx++;
3644 if ((strcmp(args[myidx], "store") == 0) ||
3645 (strcmp(args[myidx], "store-request") == 0)) {
3646 myidx++;
3647 flags = STK_IS_STORE;
3648 }
3649 else if (strcmp(args[myidx], "store-response") == 0) {
3650 myidx++;
3651 flags = STK_IS_STORE | STK_ON_RSP;
3652 }
3653 else if (strcmp(args[myidx], "match") == 0) {
3654 myidx++;
3655 flags = STK_IS_MATCH;
3656 }
3657 else if (strcmp(args[myidx], "on") == 0) {
3658 myidx++;
3659 flags = STK_IS_MATCH | STK_IS_STORE;
3660 }
3661 else {
3662 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
3665 }
3666
3667 if (*(args[myidx]) == 0) {
3668 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3669 err_code |= ERR_ALERT | ERR_FATAL;
3670 goto out;
3671 }
3672
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003673 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003674 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003675 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003676 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003677 err_code |= ERR_ALERT | ERR_FATAL;
3678 goto out;
3679 }
3680
3681 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003682 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3683 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3684 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003685 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003686 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003687 goto out;
3688 }
3689 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003690 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3691 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3692 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003693 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003694 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003695 goto out;
3696 }
3697 }
3698
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003699 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003700 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003701
Emeric Brunb982a3d2010-01-04 15:45:53 +01003702 if (strcmp(args[myidx], "table") == 0) {
3703 myidx++;
3704 name = args[myidx++];
3705 }
3706
Willy Tarreauef6494c2010-01-28 17:12:36 +01003707 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003708 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3709 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3710 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003711 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003712 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003713 goto out;
3714 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003715 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003716 else if (*(args[myidx])) {
3717 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3718 file, linenum, args[0], args[myidx]);
3719 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003720 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003721 goto out;
3722 }
Emeric Brun97679e72010-09-23 17:56:44 +02003723 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003724 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003725 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003726 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003727
Emeric Brunb982a3d2010-01-04 15:45:53 +01003728 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3729 rule->cond = cond;
3730 rule->expr = expr;
3731 rule->flags = flags;
3732 rule->table.name = name ? strdup(name) : NULL;
3733 LIST_INIT(&rule->list);
3734 if (flags & STK_ON_RSP)
3735 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3736 else
3737 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3738 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003739 else if (!strcmp(args[0], "stats")) {
3740 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3741 curproxy->uri_auth = NULL; /* we must detach from the default config */
3742
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003743 if (!*args[1]) {
3744 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003745 } else if (!strcmp(args[1], "admin")) {
3746 struct stats_admin_rule *rule;
3747
3748 if (curproxy == &defproxy) {
3749 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3750 err_code |= ERR_ALERT | ERR_FATAL;
3751 goto out;
3752 }
3753
3754 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3755 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3756 err_code |= ERR_ALERT | ERR_ABORT;
3757 goto out;
3758 }
3759
3760 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3761 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3762 file, linenum, args[0], args[1]);
3763 err_code |= ERR_ALERT | ERR_FATAL;
3764 goto out;
3765 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003766 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3767 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3768 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003769 err_code |= ERR_ALERT | ERR_FATAL;
3770 goto out;
3771 }
3772
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003773 err_code |= warnif_cond_conflicts(cond,
3774 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3775 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003776
3777 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3778 rule->cond = cond;
3779 LIST_INIT(&rule->list);
3780 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 } else if (!strcmp(args[1], "uri")) {
3782 if (*(args[2]) == 0) {
3783 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003784 err_code |= ERR_ALERT | ERR_FATAL;
3785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003786 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3787 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_ALERT | ERR_ABORT;
3789 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003790 }
3791 } else if (!strcmp(args[1], "realm")) {
3792 if (*(args[2]) == 0) {
3793 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003794 err_code |= ERR_ALERT | ERR_FATAL;
3795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003796 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3797 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003798 err_code |= ERR_ALERT | ERR_ABORT;
3799 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003800 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003801 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003802 unsigned interval;
3803
3804 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3805 if (err) {
3806 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3807 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003808 err_code |= ERR_ALERT | ERR_FATAL;
3809 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003810 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3811 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003812 err_code |= ERR_ALERT | ERR_ABORT;
3813 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003814 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003815 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003816 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003817
3818 if (curproxy == &defproxy) {
3819 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3820 err_code |= ERR_ALERT | ERR_FATAL;
3821 goto out;
3822 }
3823
3824 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3825 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3826 err_code |= ERR_ALERT | ERR_ABORT;
3827 goto out;
3828 }
3829
Willy Tarreauff011f22011-01-06 17:51:27 +01003830 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3831 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003832 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3833 file, linenum, args[0]);
3834 err_code |= ERR_WARN;
3835 }
3836
Willy Tarreauff011f22011-01-06 17:51:27 +01003837 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003838
Willy Tarreauff011f22011-01-06 17:51:27 +01003839 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003840 err_code |= ERR_ALERT | ERR_ABORT;
3841 goto out;
3842 }
3843
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003844 err_code |= warnif_cond_conflicts(rule->cond,
3845 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3846 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003847 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003848
Willy Tarreaubaaee002006-06-26 02:48:02 +02003849 } else if (!strcmp(args[1], "auth")) {
3850 if (*(args[2]) == 0) {
3851 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003852 err_code |= ERR_ALERT | ERR_FATAL;
3853 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003854 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3855 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003856 err_code |= ERR_ALERT | ERR_ABORT;
3857 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003858 }
3859 } else if (!strcmp(args[1], "scope")) {
3860 if (*(args[2]) == 0) {
3861 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003864 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3865 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003866 err_code |= ERR_ALERT | ERR_ABORT;
3867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 }
3869 } else if (!strcmp(args[1], "enable")) {
3870 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3871 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003872 err_code |= ERR_ALERT | ERR_ABORT;
3873 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003874 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003875 } else if (!strcmp(args[1], "hide-version")) {
3876 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3877 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003878 err_code |= ERR_ALERT | ERR_ABORT;
3879 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003880 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003881 } else if (!strcmp(args[1], "show-legends")) {
3882 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3883 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3884 err_code |= ERR_ALERT | ERR_ABORT;
3885 goto out;
3886 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003887 } else if (!strcmp(args[1], "show-node")) {
3888
3889 if (*args[2]) {
3890 int i;
3891 char c;
3892
3893 for (i=0; args[2][i]; i++) {
3894 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003895 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3896 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003897 break;
3898 }
3899
3900 if (!i || args[2][i]) {
3901 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3902 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3903 file, linenum, args[0], args[1]);
3904 err_code |= ERR_ALERT | ERR_FATAL;
3905 goto out;
3906 }
3907 }
3908
3909 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3910 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3911 err_code |= ERR_ALERT | ERR_ABORT;
3912 goto out;
3913 }
3914 } else if (!strcmp(args[1], "show-desc")) {
3915 char *desc = NULL;
3916
3917 if (*args[2]) {
3918 int i, len=0;
3919 char *d;
3920
Willy Tarreau348acfe2014-04-14 15:00:39 +02003921 for (i = 2; *args[i]; i++)
3922 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003923
3924 desc = d = (char *)calloc(1, len);
3925
Willy Tarreau348acfe2014-04-14 15:00:39 +02003926 d += snprintf(d, desc + len - d, "%s", args[2]);
3927 for (i = 3; *args[i]; i++)
3928 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003929 }
3930
3931 if (!*args[2] && !global.desc)
3932 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3933 file, linenum, args[1]);
3934 else {
3935 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3936 free(desc);
3937 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3938 err_code |= ERR_ALERT | ERR_ABORT;
3939 goto out;
3940 }
3941 free(desc);
3942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003943 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003944stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003945 Alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003946 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003949 }
3950 }
3951 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003952 int optnum;
3953
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003954 if (*(args[1]) == '\0') {
3955 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3956 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003959 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003960
3961 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3962 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003963 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3964 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3965 file, linenum, cfg_opts[optnum].name);
3966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
3968 }
Willy Tarreau93893792009-07-23 13:19:11 +02003969 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3970 err_code |= ERR_WARN;
3971 goto out;
3972 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003973
Willy Tarreau3842f002009-06-14 11:39:52 +02003974 curproxy->no_options &= ~cfg_opts[optnum].val;
3975 curproxy->options &= ~cfg_opts[optnum].val;
3976
3977 switch (kwm) {
3978 case KWM_STD:
3979 curproxy->options |= cfg_opts[optnum].val;
3980 break;
3981 case KWM_NO:
3982 curproxy->no_options |= cfg_opts[optnum].val;
3983 break;
3984 case KWM_DEF: /* already cleared */
3985 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003986 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003987
Willy Tarreau93893792009-07-23 13:19:11 +02003988 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003989 }
3990 }
3991
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003992 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3993 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003994 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3995 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3996 file, linenum, cfg_opts2[optnum].name);
3997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
3999 }
Willy Tarreau93893792009-07-23 13:19:11 +02004000 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4001 err_code |= ERR_WARN;
4002 goto out;
4003 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004004
Willy Tarreau3842f002009-06-14 11:39:52 +02004005 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4006 curproxy->options2 &= ~cfg_opts2[optnum].val;
4007
4008 switch (kwm) {
4009 case KWM_STD:
4010 curproxy->options2 |= cfg_opts2[optnum].val;
4011 break;
4012 case KWM_NO:
4013 curproxy->no_options2 |= cfg_opts2[optnum].val;
4014 break;
4015 case KWM_DEF: /* already cleared */
4016 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004017 }
Willy Tarreau93893792009-07-23 13:19:11 +02004018 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004019 }
4020 }
4021
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004022 /* HTTP options override each other. They can be cancelled using
4023 * "no option xxx" which only switches to default mode if the mode
4024 * was this one (useful for cancelling options set in defaults
4025 * sections).
4026 */
4027 if (strcmp(args[1], "httpclose") == 0) {
4028 if (kwm == KWM_STD) {
4029 curproxy->options &= ~PR_O_HTTP_MODE;
4030 curproxy->options |= PR_O_HTTP_PCL;
4031 goto out;
4032 }
4033 else if (kwm == KWM_NO) {
4034 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4035 curproxy->options &= ~PR_O_HTTP_MODE;
4036 goto out;
4037 }
4038 }
4039 else if (strcmp(args[1], "forceclose") == 0) {
4040 if (kwm == KWM_STD) {
4041 curproxy->options &= ~PR_O_HTTP_MODE;
4042 curproxy->options |= PR_O_HTTP_FCL;
4043 goto out;
4044 }
4045 else if (kwm == KWM_NO) {
4046 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4047 curproxy->options &= ~PR_O_HTTP_MODE;
4048 goto out;
4049 }
4050 }
4051 else if (strcmp(args[1], "http-server-close") == 0) {
4052 if (kwm == KWM_STD) {
4053 curproxy->options &= ~PR_O_HTTP_MODE;
4054 curproxy->options |= PR_O_HTTP_SCL;
4055 goto out;
4056 }
4057 else if (kwm == KWM_NO) {
4058 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4059 curproxy->options &= ~PR_O_HTTP_MODE;
4060 goto out;
4061 }
4062 }
4063 else if (strcmp(args[1], "http-keep-alive") == 0) {
4064 if (kwm == KWM_STD) {
4065 curproxy->options &= ~PR_O_HTTP_MODE;
4066 curproxy->options |= PR_O_HTTP_KAL;
4067 goto out;
4068 }
4069 else if (kwm == KWM_NO) {
4070 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4071 curproxy->options &= ~PR_O_HTTP_MODE;
4072 goto out;
4073 }
4074 }
4075 else if (strcmp(args[1], "http-tunnel") == 0) {
4076 if (kwm == KWM_STD) {
4077 curproxy->options &= ~PR_O_HTTP_MODE;
4078 curproxy->options |= PR_O_HTTP_TUN;
4079 goto out;
4080 }
4081 else if (kwm == KWM_NO) {
4082 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4083 curproxy->options &= ~PR_O_HTTP_MODE;
4084 goto out;
4085 }
4086 }
4087
Willy Tarreau3842f002009-06-14 11:39:52 +02004088 if (kwm != KWM_STD) {
4089 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004090 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004091 err_code |= ERR_ALERT | ERR_FATAL;
4092 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004093 }
4094
Emeric Brun3a058f32009-06-30 18:26:00 +02004095 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004096 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004097 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004098 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004099 if (*(args[2]) != '\0') {
4100 if (!strcmp(args[2], "clf")) {
4101 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004102 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004103 } else {
4104 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02004105 err_code |= ERR_ALERT | ERR_FATAL;
4106 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004107 }
4108 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004109 if (curproxy->conf.logformat_string != default_http_log_format &&
4110 curproxy->conf.logformat_string != default_tcp_log_format &&
4111 curproxy->conf.logformat_string != clf_http_log_format)
4112 free(curproxy->conf.logformat_string);
4113 curproxy->conf.logformat_string = logformat;
4114
4115 free(curproxy->conf.lfs_file);
4116 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4117 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004118 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004119 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004120 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004121 if (curproxy->conf.logformat_string != default_http_log_format &&
4122 curproxy->conf.logformat_string != default_tcp_log_format &&
4123 curproxy->conf.logformat_string != clf_http_log_format)
4124 free(curproxy->conf.logformat_string);
4125 curproxy->conf.logformat_string = default_tcp_log_format;
4126
4127 free(curproxy->conf.lfs_file);
4128 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4129 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004130 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004131 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004132 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004133 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004134 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004135
4136 if (curproxy->cap & PR_CAP_FE)
4137 curproxy->options |= PR_O_TCP_CLI_KA;
4138 if (curproxy->cap & PR_CAP_BE)
4139 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004140 }
4141 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004142 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004143 err_code |= ERR_WARN;
4144
Willy Tarreaubaaee002006-06-26 02:48:02 +02004145 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004146 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004147 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004148 curproxy->options2 &= ~PR_O2_CHK_ANY;
4149 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004150 if (!*args[2]) { /* no argument */
4151 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4152 curproxy->check_len = strlen(DEF_CHECK_REQ);
4153 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004154 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004155 curproxy->check_req = (char *)malloc(reqlen);
4156 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004157 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004158 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004159 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004160 if (*args[4])
4161 reqlen += strlen(args[4]);
4162 else
4163 reqlen += strlen("HTTP/1.0");
4164
4165 curproxy->check_req = (char *)malloc(reqlen);
4166 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004167 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004168 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004169 }
4170 else if (!strcmp(args[1], "ssl-hello-chk")) {
4171 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004172 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004173 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004174
Willy Tarreaua534fea2008-08-03 12:19:50 +02004175 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004176 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004177 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004178 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004179 }
Willy Tarreau23677902007-05-08 23:50:35 +02004180 else if (!strcmp(args[1], "smtpchk")) {
4181 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004182 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004183 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004184 curproxy->options2 &= ~PR_O2_CHK_ANY;
4185 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004186
4187 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4188 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4189 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4190 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4191 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4192 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4193 curproxy->check_req = (char *)malloc(reqlen);
4194 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4195 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4196 } else {
4197 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4198 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4199 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4200 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4201 }
4202 }
4203 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004204 else if (!strcmp(args[1], "pgsql-check")) {
4205 /* use PostgreSQL request to check servers' health */
4206 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4207 err_code |= ERR_WARN;
4208
4209 free(curproxy->check_req);
4210 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004211 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004212 curproxy->options2 |= PR_O2_PGSQL_CHK;
4213
4214 if (*(args[2])) {
4215 int cur_arg = 2;
4216
4217 while (*(args[cur_arg])) {
4218 if (strcmp(args[cur_arg], "user") == 0) {
4219 char * packet;
4220 uint32_t packet_len;
4221 uint32_t pv;
4222
4223 /* suboption header - needs additional argument for it */
4224 if (*(args[cur_arg+1]) == 0) {
4225 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4226 file, linenum, args[0], args[1], args[cur_arg]);
4227 err_code |= ERR_ALERT | ERR_FATAL;
4228 goto out;
4229 }
4230
4231 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4232 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4233 pv = htonl(0x30000); /* protocol version 3.0 */
4234
4235 packet = (char*) calloc(1, packet_len);
4236
4237 memcpy(packet + 4, &pv, 4);
4238
4239 /* copy "user" */
4240 memcpy(packet + 8, "user", 4);
4241
4242 /* copy username */
4243 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4244
4245 free(curproxy->check_req);
4246 curproxy->check_req = packet;
4247 curproxy->check_len = packet_len;
4248
4249 packet_len = htonl(packet_len);
4250 memcpy(packet, &packet_len, 4);
4251 cur_arg += 2;
4252 } else {
4253 /* unknown suboption - catchall */
4254 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4255 file, linenum, args[0], args[1]);
4256 err_code |= ERR_ALERT | ERR_FATAL;
4257 goto out;
4258 }
4259 } /* end while loop */
4260 }
4261 }
4262
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004263 else if (!strcmp(args[1], "redis-check")) {
4264 /* use REDIS PING request to check servers' health */
4265 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4266 err_code |= ERR_WARN;
4267
4268 free(curproxy->check_req);
4269 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004270 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004271 curproxy->options2 |= PR_O2_REDIS_CHK;
4272
4273 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4274 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4275 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4276 }
4277
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004278 else if (!strcmp(args[1], "mysql-check")) {
4279 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004280 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4281 err_code |= ERR_WARN;
4282
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004283 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004284 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004285 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004286 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004287
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004288 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004289 * const char mysql40_client_auth_pkt[] = {
4290 * "\x0e\x00\x00" // packet length
4291 * "\x01" // packet number
4292 * "\x00\x00" // client capabilities
4293 * "\x00\x00\x01" // max packet
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
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004302 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4303 * const char mysql41_client_auth_pkt[] = {
4304 * "\x0e\x00\x00\" // packet length
4305 * "\x01" // packet number
4306 * "\x00\x00\x00\x00" // client capabilities
4307 * "\x00\x00\x00\x01" // max packet
4308 * "\x21" // character set (UTF-8)
4309 * char[23] // All zeroes
4310 * "haproxy\x00" // username (null terminated string)
4311 * "\x00" // filler (always 0x00)
4312 * "\x01\x00\x00" // packet length
4313 * "\x00" // packet number
4314 * "\x01" // COM_QUIT command
4315 * };
4316 */
4317
4318
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004319 if (*(args[2])) {
4320 int cur_arg = 2;
4321
4322 while (*(args[cur_arg])) {
4323 if (strcmp(args[cur_arg], "user") == 0) {
4324 char *mysqluser;
4325 int packetlen, reqlen, userlen;
4326
4327 /* suboption header - needs additional argument for it */
4328 if (*(args[cur_arg+1]) == 0) {
4329 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4330 file, linenum, args[0], args[1], args[cur_arg]);
4331 err_code |= ERR_ALERT | ERR_FATAL;
4332 goto out;
4333 }
4334 mysqluser = args[cur_arg + 1];
4335 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004336
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004337 if (*(args[cur_arg+2])) {
4338 if (!strcmp(args[cur_arg+2], "post-41")) {
4339 packetlen = userlen + 7 + 27;
4340 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004341
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004342 free(curproxy->check_req);
4343 curproxy->check_req = (char *)calloc(1, reqlen);
4344 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004345
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004346 snprintf(curproxy->check_req, 4, "%c%c%c",
4347 ((unsigned char) packetlen & 0xff),
4348 ((unsigned char) (packetlen >> 8) & 0xff),
4349 ((unsigned char) (packetlen >> 16) & 0xff));
4350
4351 curproxy->check_req[3] = 1;
4352 curproxy->check_req[5] = 130;
4353 curproxy->check_req[11] = 1;
4354 curproxy->check_req[12] = 33;
4355 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4356 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4357 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4358 cur_arg += 3;
4359 } else {
4360 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4361 err_code |= ERR_ALERT | ERR_FATAL;
4362 goto out;
4363 }
4364 } else {
4365 packetlen = userlen + 7;
4366 reqlen = packetlen + 9;
4367
4368 free(curproxy->check_req);
4369 curproxy->check_req = (char *)calloc(1, reqlen);
4370 curproxy->check_len = reqlen;
4371
4372 snprintf(curproxy->check_req, 4, "%c%c%c",
4373 ((unsigned char) packetlen & 0xff),
4374 ((unsigned char) (packetlen >> 8) & 0xff),
4375 ((unsigned char) (packetlen >> 16) & 0xff));
4376
4377 curproxy->check_req[3] = 1;
4378 curproxy->check_req[5] = 128;
4379 curproxy->check_req[8] = 1;
4380 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4381 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4382 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4383 cur_arg += 2;
4384 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004385 } else {
4386 /* unknown suboption - catchall */
4387 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4388 file, linenum, args[0], args[1]);
4389 err_code |= ERR_ALERT | ERR_FATAL;
4390 goto out;
4391 }
4392 } /* end while loop */
4393 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004394 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004395 else if (!strcmp(args[1], "ldap-check")) {
4396 /* use LDAP request to check servers' health */
4397 free(curproxy->check_req);
4398 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004399 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004400 curproxy->options2 |= PR_O2_LDAP_CHK;
4401
4402 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4403 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4404 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4405 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004406 else if (!strcmp(args[1], "tcp-check")) {
4407 /* use raw TCPCHK send/expect to check servers' health */
4408 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4409 err_code |= ERR_WARN;
4410
4411 free(curproxy->check_req);
4412 curproxy->check_req = NULL;
4413 curproxy->options2 &= ~PR_O2_CHK_ANY;
4414 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4415 }
Simon Horman98637e52014-06-20 12:30:16 +09004416 else if (!strcmp(args[1], "external-check")) {
4417 /* excute an external command to check servers' health */
4418 free(curproxy->check_req);
4419 curproxy->check_req = NULL;
4420 curproxy->options2 &= ~PR_O2_CHK_ANY;
4421 curproxy->options2 |= PR_O2_EXT_CHK;
4422 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004423 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004424 int cur_arg;
4425
4426 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4427 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004428 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004429
Willy Tarreau87cf5142011-08-19 22:57:24 +02004430 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004431
4432 free(curproxy->fwdfor_hdr_name);
4433 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4434 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4435
4436 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4437 cur_arg = 2;
4438 while (*(args[cur_arg])) {
4439 if (!strcmp(args[cur_arg], "except")) {
4440 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004441 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004442 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4443 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004444 err_code |= ERR_ALERT | ERR_FATAL;
4445 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004446 }
4447 /* flush useless bits */
4448 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004449 cur_arg += 2;
4450 } else if (!strcmp(args[cur_arg], "header")) {
4451 /* suboption header - needs additional argument for it */
4452 if (*(args[cur_arg+1]) == 0) {
4453 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4454 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004455 err_code |= ERR_ALERT | ERR_FATAL;
4456 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004457 }
4458 free(curproxy->fwdfor_hdr_name);
4459 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4460 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4461 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004462 } else if (!strcmp(args[cur_arg], "if-none")) {
4463 curproxy->options &= ~PR_O_FF_ALWAYS;
4464 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004465 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004466 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004467 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004468 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004469 err_code |= ERR_ALERT | ERR_FATAL;
4470 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004471 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004472 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004473 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004474 else if (!strcmp(args[1], "originalto")) {
4475 int cur_arg;
4476
4477 /* insert x-original-to field, but not for the IP address listed as an except.
4478 * set default options (ie: bitfield, header name, etc)
4479 */
4480
4481 curproxy->options |= PR_O_ORGTO;
4482
4483 free(curproxy->orgto_hdr_name);
4484 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4485 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4486
Willy Tarreau87cf5142011-08-19 22:57:24 +02004487 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004488 cur_arg = 2;
4489 while (*(args[cur_arg])) {
4490 if (!strcmp(args[cur_arg], "except")) {
4491 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004492 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 +02004493 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4494 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004495 err_code |= ERR_ALERT | ERR_FATAL;
4496 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004497 }
4498 /* flush useless bits */
4499 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4500 cur_arg += 2;
4501 } else if (!strcmp(args[cur_arg], "header")) {
4502 /* suboption header - needs additional argument for it */
4503 if (*(args[cur_arg+1]) == 0) {
4504 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4505 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004506 err_code |= ERR_ALERT | ERR_FATAL;
4507 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004508 }
4509 free(curproxy->orgto_hdr_name);
4510 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4511 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4512 cur_arg += 2;
4513 } else {
4514 /* unknown suboption - catchall */
4515 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4516 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004517 err_code |= ERR_ALERT | ERR_FATAL;
4518 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004519 }
4520 } /* end while loop */
4521 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004522 else {
4523 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004524 err_code |= ERR_ALERT | ERR_FATAL;
4525 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004526 }
Willy Tarreau93893792009-07-23 13:19:11 +02004527 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004528 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004529 else if (!strcmp(args[0], "default_backend")) {
4530 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004531 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004532
4533 if (*(args[1]) == 0) {
4534 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004535 err_code |= ERR_ALERT | ERR_FATAL;
4536 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004537 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004538 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004539 curproxy->defbe.name = strdup(args[1]);
4540 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004541 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004542 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004543 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004544
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004545 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4546 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 +01004547 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004548 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004549 /* enable reconnections to dispatch */
4550 curproxy->options |= PR_O_REDISP;
4551 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004552 else if (!strcmp(args[0], "http-check")) {
4553 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004554 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004555
4556 if (strcmp(args[1], "disable-on-404") == 0) {
4557 /* enable a graceful server shutdown on an HTTP 404 response */
4558 curproxy->options |= PR_O_DISABLE404;
4559 }
Willy Tarreauef781042010-01-27 11:53:01 +01004560 else if (strcmp(args[1], "send-state") == 0) {
4561 /* enable emission of the apparent state of a server in HTTP checks */
4562 curproxy->options2 |= PR_O2_CHK_SNDST;
4563 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004564 else if (strcmp(args[1], "expect") == 0) {
4565 const char *ptr_arg;
4566 int cur_arg;
4567
4568 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4569 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4570 err_code |= ERR_ALERT | ERR_FATAL;
4571 goto out;
4572 }
4573
4574 cur_arg = 2;
4575 /* consider exclamation marks, sole or at the beginning of a word */
4576 while (*(ptr_arg = args[cur_arg])) {
4577 while (*ptr_arg == '!') {
4578 curproxy->options2 ^= PR_O2_EXP_INV;
4579 ptr_arg++;
4580 }
4581 if (*ptr_arg)
4582 break;
4583 cur_arg++;
4584 }
4585 /* now ptr_arg points to the beginning of a word past any possible
4586 * exclamation mark, and cur_arg is the argument which holds this word.
4587 */
4588 if (strcmp(ptr_arg, "status") == 0) {
4589 if (!*(args[cur_arg + 1])) {
4590 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4591 file, linenum, args[0], args[1], ptr_arg);
4592 err_code |= ERR_ALERT | ERR_FATAL;
4593 goto out;
4594 }
4595 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004596 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004597 curproxy->expect_str = strdup(args[cur_arg + 1]);
4598 }
4599 else if (strcmp(ptr_arg, "string") == 0) {
4600 if (!*(args[cur_arg + 1])) {
4601 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4602 file, linenum, args[0], args[1], ptr_arg);
4603 err_code |= ERR_ALERT | ERR_FATAL;
4604 goto out;
4605 }
4606 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004607 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004608 curproxy->expect_str = strdup(args[cur_arg + 1]);
4609 }
4610 else if (strcmp(ptr_arg, "rstatus") == 0) {
4611 if (!*(args[cur_arg + 1])) {
4612 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4613 file, linenum, args[0], args[1], ptr_arg);
4614 err_code |= ERR_ALERT | ERR_FATAL;
4615 goto out;
4616 }
4617 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004618 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004619 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004620 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004621 free(curproxy->expect_regex);
4622 curproxy->expect_regex = NULL;
4623 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004624 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004625 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4626 error = NULL;
4627 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4628 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4629 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4630 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004631 err_code |= ERR_ALERT | ERR_FATAL;
4632 goto out;
4633 }
4634 }
4635 else if (strcmp(ptr_arg, "rstring") == 0) {
4636 if (!*(args[cur_arg + 1])) {
4637 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4638 file, linenum, args[0], args[1], ptr_arg);
4639 err_code |= ERR_ALERT | ERR_FATAL;
4640 goto out;
4641 }
4642 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004643 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004644 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004645 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004646 free(curproxy->expect_regex);
4647 curproxy->expect_regex = NULL;
4648 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004649 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004650 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4651 error = NULL;
4652 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4653 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4654 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4655 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004656 err_code |= ERR_ALERT | ERR_FATAL;
4657 goto out;
4658 }
4659 }
4660 else {
4661 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4662 file, linenum, args[0], args[1], ptr_arg);
4663 err_code |= ERR_ALERT | ERR_FATAL;
4664 goto out;
4665 }
4666 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004667 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004668 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 +02004669 err_code |= ERR_ALERT | ERR_FATAL;
4670 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004671 }
4672 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004673 else if (!strcmp(args[0], "tcp-check")) {
4674 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4675 err_code |= ERR_WARN;
4676
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004677 if (strcmp(args[1], "connect") == 0) {
4678 const char *ptr_arg;
4679 int cur_arg;
4680 struct tcpcheck_rule *tcpcheck;
4681 struct list *l;
4682
4683 /* check if first rule is also a 'connect' action */
4684 l = (struct list *)&curproxy->tcpcheck_rules;
4685 if (l->p != l->n) {
4686 tcpcheck = (struct tcpcheck_rule *)l->n;
4687 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4688 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4689 file, linenum);
4690 err_code |= ERR_ALERT | ERR_FATAL;
4691 goto out;
4692 }
4693 }
4694
4695 cur_arg = 2;
4696 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4697 tcpcheck->action = TCPCHK_ACT_CONNECT;
4698
4699 /* parsing each parameters to fill up the rule */
4700 while (*(ptr_arg = args[cur_arg])) {
4701 /* tcp port */
4702 if (strcmp(args[cur_arg], "port") == 0) {
4703 if ( (atol(args[cur_arg + 1]) > 65535) ||
4704 (atol(args[cur_arg + 1]) < 1) ){
4705 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4706 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4707 err_code |= ERR_ALERT | ERR_FATAL;
4708 goto out;
4709 }
4710 tcpcheck->port = atol(args[cur_arg + 1]);
4711 cur_arg += 2;
4712 }
4713 /* send proxy protocol */
4714 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4715 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4716 cur_arg++;
4717 }
4718#ifdef USE_OPENSSL
4719 else if (strcmp(args[cur_arg], "ssl") == 0) {
4720 curproxy->options |= PR_O_TCPCHK_SSL;
4721 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4722 cur_arg++;
4723 }
4724#endif /* USE_OPENSSL */
4725 else {
4726#ifdef USE_OPENSSL
4727 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4728#else /* USE_OPENSSL */
4729 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4730#endif /* USE_OPENSSL */
4731 file, linenum, args[0], args[1], args[cur_arg]);
4732 err_code |= ERR_ALERT | ERR_FATAL;
4733 goto out;
4734 }
4735
4736 }
4737
4738 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4739 }
4740 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004741 if (! *(args[2]) ) {
4742 /* SEND string expected */
4743 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4744 file, linenum, args[0], args[1], args[2]);
4745 err_code |= ERR_ALERT | ERR_FATAL;
4746 goto out;
4747 } else {
4748 struct tcpcheck_rule *tcpcheck;
4749
4750 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4751
4752 tcpcheck->action = TCPCHK_ACT_SEND;
4753 tcpcheck->string_len = strlen(args[2]);
4754 tcpcheck->string = strdup(args[2]);
4755 tcpcheck->expect_regex = NULL;
4756
4757 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4758 }
4759 }
4760 else if (strcmp(args[1], "send-binary") == 0) {
4761 if (! *(args[2]) ) {
4762 /* SEND binary string expected */
4763 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4764 file, linenum, args[0], args[1], args[2]);
4765 err_code |= ERR_ALERT | ERR_FATAL;
4766 goto out;
4767 } else {
4768 struct tcpcheck_rule *tcpcheck;
4769 char *err = NULL;
4770
4771 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4772
4773 tcpcheck->action = TCPCHK_ACT_SEND;
4774 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4775 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4776 file, linenum, args[0], args[1], args[2], err);
4777 err_code |= ERR_ALERT | ERR_FATAL;
4778 goto out;
4779 }
4780 tcpcheck->expect_regex = NULL;
4781
4782 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4783 }
4784 }
4785 else if (strcmp(args[1], "expect") == 0) {
4786 const char *ptr_arg;
4787 int cur_arg;
4788 int inverse = 0;
4789
4790 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4791 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4792 err_code |= ERR_ALERT | ERR_FATAL;
4793 goto out;
4794 }
4795
4796 cur_arg = 2;
4797 /* consider exclamation marks, sole or at the beginning of a word */
4798 while (*(ptr_arg = args[cur_arg])) {
4799 while (*ptr_arg == '!') {
4800 inverse = !inverse;
4801 ptr_arg++;
4802 }
4803 if (*ptr_arg)
4804 break;
4805 cur_arg++;
4806 }
4807 /* now ptr_arg points to the beginning of a word past any possible
4808 * exclamation mark, and cur_arg is the argument which holds this word.
4809 */
4810 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004811 struct tcpcheck_rule *tcpcheck;
4812 char *err = NULL;
4813
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004814 if (!*(args[cur_arg + 1])) {
4815 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4816 file, linenum, args[0], args[1], ptr_arg);
4817 err_code |= ERR_ALERT | ERR_FATAL;
4818 goto out;
4819 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004820
4821 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4822
4823 tcpcheck->action = TCPCHK_ACT_EXPECT;
4824 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4825 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4826 file, linenum, args[0], args[1], args[2], err);
4827 err_code |= ERR_ALERT | ERR_FATAL;
4828 goto out;
4829 }
4830 tcpcheck->expect_regex = NULL;
4831 tcpcheck->inverse = inverse;
4832
4833 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4834 }
4835 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004836 struct tcpcheck_rule *tcpcheck;
4837
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004838 if (!*(args[cur_arg + 1])) {
4839 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4840 file, linenum, args[0], args[1], ptr_arg);
4841 err_code |= ERR_ALERT | ERR_FATAL;
4842 goto out;
4843 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004844
4845 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4846
4847 tcpcheck->action = TCPCHK_ACT_EXPECT;
4848 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4849 tcpcheck->string = strdup(args[cur_arg + 1]);
4850 tcpcheck->expect_regex = NULL;
4851 tcpcheck->inverse = inverse;
4852
4853 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4854 }
4855 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004856 struct tcpcheck_rule *tcpcheck;
4857
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004858 if (!*(args[cur_arg + 1])) {
4859 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4860 file, linenum, args[0], args[1], ptr_arg);
4861 err_code |= ERR_ALERT | ERR_FATAL;
4862 goto out;
4863 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004864
4865 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4866
4867 tcpcheck->action = TCPCHK_ACT_EXPECT;
4868 tcpcheck->string_len = 0;
4869 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004870 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4871 error = NULL;
4872 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4873 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4874 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4875 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004876 err_code |= ERR_ALERT | ERR_FATAL;
4877 goto out;
4878 }
4879 tcpcheck->inverse = inverse;
4880
4881 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4882 }
4883 else {
4884 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4885 file, linenum, args[0], args[1], ptr_arg);
4886 err_code |= ERR_ALERT | ERR_FATAL;
4887 goto out;
4888 }
4889 }
4890 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004891 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004892 err_code |= ERR_ALERT | ERR_FATAL;
4893 goto out;
4894 }
4895 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004896 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004897 if (curproxy == &defproxy) {
4898 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004899 err_code |= ERR_ALERT | ERR_FATAL;
4900 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004901 }
4902
Willy Tarreaub80c2302007-11-30 20:51:32 +01004903 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004904 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004905
4906 if (strcmp(args[1], "fail") == 0) {
4907 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004908 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004909 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4910 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004911 err_code |= ERR_ALERT | ERR_FATAL;
4912 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004913 }
4914
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004915 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4916 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4917 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004918 err_code |= ERR_ALERT | ERR_FATAL;
4919 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004920 }
4921 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4922 }
4923 else {
4924 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004925 err_code |= ERR_ALERT | ERR_FATAL;
4926 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004927 }
4928 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004929#ifdef TPROXY
4930 else if (!strcmp(args[0], "transparent")) {
4931 /* enable transparent proxy connections */
4932 curproxy->options |= PR_O_TRANSP;
4933 }
4934#endif
4935 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004936 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004937 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004938
Willy Tarreaubaaee002006-06-26 02:48:02 +02004939 if (*(args[1]) == 0) {
4940 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004941 err_code |= ERR_ALERT | ERR_FATAL;
4942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004943 }
4944 curproxy->maxconn = atol(args[1]);
4945 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004946 else if (!strcmp(args[0], "backlog")) { /* backlog */
4947 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004948 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004949
4950 if (*(args[1]) == 0) {
4951 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004952 err_code |= ERR_ALERT | ERR_FATAL;
4953 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004954 }
4955 curproxy->backlog = atol(args[1]);
4956 }
Willy Tarreau86034312006-12-29 00:10:33 +01004957 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004958 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004959 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004960
Willy Tarreau86034312006-12-29 00:10:33 +01004961 if (*(args[1]) == 0) {
4962 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004963 err_code |= ERR_ALERT | ERR_FATAL;
4964 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004965 }
4966 curproxy->fullconn = atol(args[1]);
4967 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004968 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4969 if (*(args[1]) == 0) {
4970 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004971 err_code |= ERR_ALERT | ERR_FATAL;
4972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004973 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004974 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4975 if (err) {
4976 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4977 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004978 err_code |= ERR_ALERT | ERR_FATAL;
4979 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004980 }
4981 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004982 }
4983 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004984 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004985 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004986 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004987
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 if (curproxy == &defproxy) {
4989 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004990 err_code |= ERR_ALERT | ERR_FATAL;
4991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004992 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004993 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004994 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004995
Willy Tarreau902636f2013-03-10 19:44:48 +01004996 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004997 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004998 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004999 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005000 goto out;
5001 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005002
5003 proto = protocol_by_family(sk->ss_family);
5004 if (!proto || !proto->connect) {
5005 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5006 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005007 err_code |= ERR_ALERT | ERR_FATAL;
5008 goto out;
5009 }
5010
5011 if (port1 != port2) {
5012 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5013 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005014 err_code |= ERR_ALERT | ERR_FATAL;
5015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005016 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005017
5018 if (!port1) {
5019 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5020 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
5023 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005024
Willy Tarreaud5191e72010-02-09 20:50:45 +01005025 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005026 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005027 }
5028 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005029 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005030 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005031
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005032 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5033 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005034 err_code |= ERR_ALERT | ERR_FATAL;
5035 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005036 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005037 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005038 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005039 /**
5040 * The syntax for hash-type config element is
5041 * hash-type {map-based|consistent} [[<algo>] avalanche]
5042 *
5043 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5044 */
5045 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005046
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005047 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5048 err_code |= ERR_WARN;
5049
5050 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005051 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5052 }
5053 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005054 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5055 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005056 else if (strcmp(args[1], "avalanche") == 0) {
5057 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]);
5058 err_code |= ERR_ALERT | ERR_FATAL;
5059 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005060 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005061 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005062 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005063 err_code |= ERR_ALERT | ERR_FATAL;
5064 goto out;
5065 }
Bhaskar98634f02013-10-29 23:30:51 -04005066
5067 /* set the hash function to use */
5068 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005069 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005070 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005071
5072 /* if consistent with no argument, then avalanche modifier is also applied */
5073 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5074 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005075 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005076 /* set the hash function */
5077 if (!strcmp(args[2], "sdbm")) {
5078 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5079 }
5080 else if (!strcmp(args[2], "djb2")) {
5081 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005082 }
5083 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005084 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005085 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005086 else if (!strcmp(args[2], "crc32")) {
5087 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5088 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005089 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005090 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 -05005091 err_code |= ERR_ALERT | ERR_FATAL;
5092 goto out;
5093 }
5094
5095 /* set the hash modifier */
5096 if (!strcmp(args[3], "avalanche")) {
5097 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5098 }
5099 else if (*args[3]) {
5100 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5101 err_code |= ERR_ALERT | ERR_FATAL;
5102 goto out;
5103 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005104 }
William Lallemanda73203e2012-03-12 12:48:57 +01005105 }
William Lallemanda73203e2012-03-12 12:48:57 +01005106 else if (strcmp(args[0], "unique-id-format") == 0) {
5107 if (!*(args[1])) {
5108 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5109 err_code |= ERR_ALERT | ERR_FATAL;
5110 goto out;
5111 }
William Lallemand3203ff42012-11-11 17:30:56 +01005112 if (*(args[2])) {
5113 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5114 err_code |= ERR_ALERT | ERR_FATAL;
5115 goto out;
5116 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005117 free(curproxy->conf.uniqueid_format_string);
5118 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005119
Willy Tarreau62a61232013-04-12 18:13:46 +02005120 free(curproxy->conf.uif_file);
5121 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5122 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005123 }
William Lallemanda73203e2012-03-12 12:48:57 +01005124
5125 else if (strcmp(args[0], "unique-id-header") == 0) {
5126 if (!*(args[1])) {
5127 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5128 err_code |= ERR_ALERT | ERR_FATAL;
5129 goto out;
5130 }
5131 free(curproxy->header_unique_id);
5132 curproxy->header_unique_id = strdup(args[1]);
5133 }
5134
William Lallemand723b73a2012-02-08 16:37:49 +01005135 else if (strcmp(args[0], "log-format") == 0) {
5136 if (!*(args[1])) {
5137 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5138 err_code |= ERR_ALERT | ERR_FATAL;
5139 goto out;
5140 }
William Lallemand3203ff42012-11-11 17:30:56 +01005141 if (*(args[2])) {
5142 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5143 err_code |= ERR_ALERT | ERR_FATAL;
5144 goto out;
5145 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005146
Willy Tarreau62a61232013-04-12 18:13:46 +02005147 if (curproxy->conf.logformat_string != default_http_log_format &&
5148 curproxy->conf.logformat_string != default_tcp_log_format &&
5149 curproxy->conf.logformat_string != clf_http_log_format)
5150 free(curproxy->conf.logformat_string);
5151 curproxy->conf.logformat_string = strdup(args[1]);
5152
5153 free(curproxy->conf.lfs_file);
5154 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5155 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005156
5157 /* get a chance to improve log-format error reporting by
5158 * reporting the correct line-number when possible.
5159 */
5160 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5161 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5162 file, linenum, curproxy->id);
5163 err_code |= ERR_WARN;
5164 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005165 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005166 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5167 if (*(args[1]) == 0) {
5168 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5169 err_code |= ERR_ALERT | ERR_FATAL;
5170 goto out;
5171 }
5172 free(curproxy->log_tag);
5173 curproxy->log_tag = strdup(args[1]);
5174 }
William Lallemand0f99e342011-10-12 17:50:54 +02005175 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5176 /* delete previous herited or defined syslog servers */
5177 struct logsrv *back;
5178
5179 if (*(args[1]) != 0) {
5180 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5181 err_code |= ERR_ALERT | ERR_FATAL;
5182 goto out;
5183 }
5184
William Lallemand723b73a2012-02-08 16:37:49 +01005185 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5186 LIST_DEL(&tmplogsrv->list);
5187 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005188 }
5189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005190 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005191 struct logsrv *logsrv;
5192
Willy Tarreaubaaee002006-06-26 02:48:02 +02005193 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005194 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005195 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005196 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005197 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005198 LIST_INIT(&node->list);
5199 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5200 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005201 }
5202 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005203 struct sockaddr_storage *sk;
5204 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005205 int arg = 0;
5206 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005207
5208 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005209
Willy Tarreau18324f52014-06-27 18:10:07 +02005210 /* just after the address, a length may be specified */
5211 if (strcmp(args[arg+2], "len") == 0) {
5212 len = atoi(args[arg+3]);
5213 if (len < 80 || len > 65535) {
5214 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5215 file, linenum, args[arg+3]);
5216 err_code |= ERR_ALERT | ERR_FATAL;
5217 goto out;
5218 }
5219 logsrv->maxlen = len;
5220
5221 /* skip these two args */
5222 arg += 2;
5223 }
5224 else
5225 logsrv->maxlen = MAX_SYSLOG_LEN;
5226
5227 if (logsrv->maxlen > global.max_syslog_len) {
5228 global.max_syslog_len = logsrv->maxlen;
5229 logline = realloc(logline, global.max_syslog_len + 1);
5230 }
5231
5232 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005233 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005234 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005235 err_code |= ERR_ALERT | ERR_FATAL;
5236 goto out;
5237
Willy Tarreaubaaee002006-06-26 02:48:02 +02005238 }
5239
William Lallemand0f99e342011-10-12 17:50:54 +02005240 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005241 if (*(args[arg+3])) {
5242 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005243 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005244 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005245 err_code |= ERR_ALERT | ERR_FATAL;
5246 goto out;
5247
Willy Tarreaubaaee002006-06-26 02:48:02 +02005248 }
5249 }
5250
William Lallemand0f99e342011-10-12 17:50:54 +02005251 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005252 if (*(args[arg+4])) {
5253 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005254 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005255 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005256 err_code |= ERR_ALERT | ERR_FATAL;
5257 goto out;
5258
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005259 }
5260 }
5261
Willy Tarreau902636f2013-03-10 19:44:48 +01005262 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005263 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005264 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005265 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005266 goto out;
5267 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005268
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005269 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005270
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005271 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005272 if (port1 != port2) {
5273 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5274 file, linenum, args[0], args[1]);
5275 err_code |= ERR_ALERT | ERR_FATAL;
5276 goto out;
5277 }
5278
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005279 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005280 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005281 }
William Lallemand0f99e342011-10-12 17:50:54 +02005282
5283 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005284 }
5285 else {
5286 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5287 file, linenum);
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 }
5291 }
5292 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005293 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005294 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005295 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005296 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005297
Willy Tarreau977b8e42006-12-29 14:19:17 +01005298 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005299 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005300
Willy Tarreaubaaee002006-06-26 02:48:02 +02005301 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005302 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5303 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005304 err_code |= ERR_ALERT | ERR_FATAL;
5305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005307
5308 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005309 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5310 free(curproxy->conn_src.iface_name);
5311 curproxy->conn_src.iface_name = NULL;
5312 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005313
Willy Tarreau902636f2013-03-10 19:44:48 +01005314 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005315 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005316 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005317 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005318 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005319 goto out;
5320 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005321
5322 proto = protocol_by_family(sk->ss_family);
5323 if (!proto || !proto->connect) {
5324 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005325 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005326 err_code |= ERR_ALERT | ERR_FATAL;
5327 goto out;
5328 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005329
5330 if (port1 != port2) {
5331 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5332 file, linenum, args[0], args[1]);
5333 err_code |= ERR_ALERT | ERR_FATAL;
5334 goto out;
5335 }
5336
Willy Tarreauef9a3602012-12-08 22:29:20 +01005337 curproxy->conn_src.source_addr = *sk;
5338 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005339
5340 cur_arg = 2;
5341 while (*(args[cur_arg])) {
5342 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005343#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5344#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005345 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005346 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5347 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005348 err_code |= ERR_ALERT | ERR_FATAL;
5349 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005350 }
5351#endif
5352 if (!*args[cur_arg + 1]) {
5353 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5354 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005355 err_code |= ERR_ALERT | ERR_FATAL;
5356 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005357 }
5358
5359 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005360 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5361 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005362 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005363 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5364 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005365 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5366 char *name, *end;
5367
5368 name = args[cur_arg+1] + 7;
5369 while (isspace(*name))
5370 name++;
5371
5372 end = name;
5373 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5374 end++;
5375
Willy Tarreauef9a3602012-12-08 22:29:20 +01005376 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5377 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5378 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5379 curproxy->conn_src.bind_hdr_len = end - name;
5380 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5381 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5382 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005383
5384 /* now look for an occurrence number */
5385 while (isspace(*end))
5386 end++;
5387 if (*end == ',') {
5388 end++;
5389 name = end;
5390 if (*end == '-')
5391 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005392 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005393 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005394 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005395 }
5396
Willy Tarreauef9a3602012-12-08 22:29:20 +01005397 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005398 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5399 " occurrences values smaller than %d.\n",
5400 file, linenum, MAX_HDR_HISTORY);
5401 err_code |= ERR_ALERT | ERR_FATAL;
5402 goto out;
5403 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005404 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005405 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005406
Willy Tarreau902636f2013-03-10 19:44:48 +01005407 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005408 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005409 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005410 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005411 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005412 goto out;
5413 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005414
5415 proto = protocol_by_family(sk->ss_family);
5416 if (!proto || !proto->connect) {
5417 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5418 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005419 err_code |= ERR_ALERT | ERR_FATAL;
5420 goto out;
5421 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005422
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005423 if (port1 != port2) {
5424 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5425 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005426 err_code |= ERR_ALERT | ERR_FATAL;
5427 goto out;
5428 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005429 curproxy->conn_src.tproxy_addr = *sk;
5430 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005431 }
5432 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005433#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005434 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005435#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005436#else /* no TPROXY support */
5437 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005438 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005439 err_code |= ERR_ALERT | ERR_FATAL;
5440 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005441#endif
5442 cur_arg += 2;
5443 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005444 }
5445
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005446 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5447#ifdef SO_BINDTODEVICE
5448 if (!*args[cur_arg + 1]) {
5449 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5450 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005451 err_code |= ERR_ALERT | ERR_FATAL;
5452 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005453 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005454 free(curproxy->conn_src.iface_name);
5455 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5456 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005457 global.last_checks |= LSTCHK_NETADM;
5458#else
5459 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5460 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005461 err_code |= ERR_ALERT | ERR_FATAL;
5462 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005463#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005464 cur_arg += 2;
5465 continue;
5466 }
5467 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005468 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005469 err_code |= ERR_ALERT | ERR_FATAL;
5470 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005472 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005473 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5474 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5475 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005476 err_code |= ERR_ALERT | ERR_FATAL;
5477 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005478 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005479 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005480 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005481 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5482 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005483 err_code |= ERR_ALERT | ERR_FATAL;
5484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005485 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005486
5487 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005488 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005489 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005490 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005492 }
5493 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005494 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005495 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005496 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005497 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005499 }
5500 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005501 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005502 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005503 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005504 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005505 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005506 }
5507 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005508 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005509 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005510 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005511 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005512 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005513 }
5514 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005515 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005516 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005517 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005518 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005520 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005521 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005522 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005523 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005524 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005525 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005526 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005527 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005528 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005529 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005530 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005531 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005532 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005533 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005534
5535 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5536 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 +01005537 }
5538 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005539 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005540 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005541 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005542 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005543 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005544
5545 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5546 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 +01005547 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005548 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005549 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005550 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5551 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005552 err_code |= ERR_ALERT | ERR_FATAL;
5553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005554 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005555
5556 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005557 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005558 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005559 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005561 }
5562 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005563 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005564 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005565 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005566 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005567 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005568 }
5569 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005570 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005571 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005572 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005573 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005575 }
5576 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005577 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005578 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005579 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005580 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005582 }
5583 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005584 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005585 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005586 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005587 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005589 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005590 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005591 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005592 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005593 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005594 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005595 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005596 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005597 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005598 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005599
Willy Tarreaubaaee002006-06-26 02:48:02 +02005600 if (curproxy == &defproxy) {
5601 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005602 err_code |= ERR_ALERT | ERR_FATAL;
5603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005604 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005605 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005606 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005607
Willy Tarreaubaaee002006-06-26 02:48:02 +02005608 if (*(args[1]) == 0) {
5609 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005610 err_code |= ERR_ALERT | ERR_FATAL;
5611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005612 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005613
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005614 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005615 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5616 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5617 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005618 err_code |= ERR_ALERT | ERR_FATAL;
5619 goto out;
5620 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005621 err_code |= warnif_cond_conflicts(cond,
5622 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5623 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005624 }
5625 else if (*args[2]) {
5626 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5627 file, linenum, args[0], args[2]);
5628 err_code |= ERR_ALERT | ERR_FATAL;
5629 goto out;
5630 }
5631
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005632 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005633 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005634 wl->s = strdup(args[1]);
5635 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005636 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005637 }
5638 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005639 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005640 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5641 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005642 err_code |= ERR_ALERT | ERR_FATAL;
5643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005644 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005645
Willy Tarreauade5ec42010-01-28 19:33:49 +01005646 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005647 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005648 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005649 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005651 }
5652 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005653 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005654 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005655 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005656 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005657 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005658 }
5659 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005660 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005661 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005662 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005663 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005665 }
5666 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005667 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005668 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5669 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005670 err_code |= ERR_ALERT | ERR_FATAL;
5671 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005672 }
5673
Willy Tarreauade5ec42010-01-28 19:33:49 +01005674 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005675 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005676 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005677 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005678 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005679 }
5680 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005681 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005682 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005683 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005684 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005685 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005686 }
5687 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005688 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005689 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005690 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005691 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005693 }
5694 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005695 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005696
Willy Tarreaubaaee002006-06-26 02:48:02 +02005697 if (curproxy == &defproxy) {
5698 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005699 err_code |= ERR_ALERT | ERR_FATAL;
5700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005701 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005702 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005703 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005704
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705 if (*(args[1]) == 0) {
5706 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005707 err_code |= ERR_ALERT | ERR_FATAL;
5708 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005709 }
5710
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005711 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005712 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5713 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5714 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005715 err_code |= ERR_ALERT | ERR_FATAL;
5716 goto out;
5717 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005718 err_code |= warnif_cond_conflicts(cond,
5719 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5720 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005721 }
5722 else if (*args[2]) {
5723 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5724 file, linenum, args[0], args[2]);
5725 err_code |= ERR_ALERT | ERR_FATAL;
5726 goto out;
5727 }
5728
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005729 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005730 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005731 wl->s = strdup(args[1]);
5732 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005733 }
5734 else if (!strcmp(args[0], "errorloc") ||
5735 !strcmp(args[0], "errorloc302") ||
5736 !strcmp(args[0], "errorloc303")) { /* error location */
5737 int errnum, errlen;
5738 char *err;
5739
Willy Tarreau977b8e42006-12-29 14:19:17 +01005740 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005741 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005742
Willy Tarreaubaaee002006-06-26 02:48:02 +02005743 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005744 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005745 err_code |= ERR_ALERT | ERR_FATAL;
5746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005747 }
5748
5749 errnum = atol(args[1]);
5750 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005751 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5752 err = malloc(errlen);
5753 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005754 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005755 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5756 err = malloc(errlen);
5757 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005758 }
5759
Willy Tarreau0f772532006-12-23 20:51:41 +01005760 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5761 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005762 chunk_destroy(&curproxy->errmsg[rc]);
5763 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005764 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005766 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005767
5768 if (rc >= HTTP_ERR_SIZE) {
5769 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5770 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771 free(err);
5772 }
5773 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005774 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5775 int errnum, errlen, fd;
5776 char *err;
5777 struct stat stat;
5778
5779 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005780 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005781
5782 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005783 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005784 err_code |= ERR_ALERT | ERR_FATAL;
5785 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005786 }
5787
5788 fd = open(args[2], O_RDONLY);
5789 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5790 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5791 file, linenum, args[2], args[1]);
5792 if (fd >= 0)
5793 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005794 err_code |= ERR_ALERT | ERR_FATAL;
5795 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005796 }
5797
Willy Tarreau27a674e2009-08-17 07:23:33 +02005798 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005799 errlen = stat.st_size;
5800 } else {
5801 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005802 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005803 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005804 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005805 }
5806
5807 err = malloc(errlen); /* malloc() must succeed during parsing */
5808 errnum = read(fd, err, errlen);
5809 if (errnum != errlen) {
5810 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5811 file, linenum, args[2], args[1]);
5812 close(fd);
5813 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005814 err_code |= ERR_ALERT | ERR_FATAL;
5815 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005816 }
5817 close(fd);
5818
5819 errnum = atol(args[1]);
5820 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5821 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005822 chunk_destroy(&curproxy->errmsg[rc]);
5823 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005824 break;
5825 }
5826 }
5827
5828 if (rc >= HTTP_ERR_SIZE) {
5829 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5830 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005831 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005832 free(err);
5833 }
5834 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005835 else if (!strcmp(args[0], "compression")) {
5836 struct comp *comp;
5837 if (curproxy->comp == NULL) {
5838 comp = calloc(1, sizeof(struct comp));
5839 curproxy->comp = comp;
5840 } else {
5841 comp = curproxy->comp;
5842 }
5843
5844 if (!strcmp(args[1], "algo")) {
5845 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005846 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005847
William Lallemand82fe75c2012-10-23 10:25:10 +02005848 cur_arg = 2;
5849 if (!*args[cur_arg]) {
5850 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5851 file, linenum, args[0]);
5852 err_code |= ERR_ALERT | ERR_FATAL;
5853 goto out;
5854 }
5855 while (*(args[cur_arg])) {
5856 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5857 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5858 file, linenum, args[0], args[cur_arg]);
5859 err_code |= ERR_ALERT | ERR_FATAL;
5860 goto out;
5861 }
William Lallemand552df672012-11-07 13:21:47 +01005862 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5863 curproxy->comp->algos->end(&ctx);
5864 } else {
5865 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5866 file, linenum, args[0], args[cur_arg]);
5867 err_code |= ERR_ALERT | ERR_FATAL;
5868 goto out;
5869 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005870 cur_arg ++;
5871 continue;
5872 }
5873 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005874 else if (!strcmp(args[1], "offload")) {
5875 comp->offload = 1;
5876 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005877 else if (!strcmp(args[1], "type")) {
5878 int cur_arg;
5879 cur_arg = 2;
5880 if (!*args[cur_arg]) {
5881 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5882 file, linenum, args[0]);
5883 err_code |= ERR_ALERT | ERR_FATAL;
5884 goto out;
5885 }
5886 while (*(args[cur_arg])) {
5887 comp_append_type(comp, args[cur_arg]);
5888 cur_arg ++;
5889 continue;
5890 }
5891 }
5892 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005893 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005894 file, linenum, args[0]);
5895 err_code |= ERR_ALERT | ERR_FATAL;
5896 goto out;
5897 }
5898 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005899 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005900 struct cfg_kw_list *kwl;
5901 int index;
5902
5903 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5904 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5905 if (kwl->kw[index].section != CFG_LISTEN)
5906 continue;
5907 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5908 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005909 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005910 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005911 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005912 err_code |= ERR_ALERT | ERR_FATAL;
5913 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005914 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005915 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005916 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005917 err_code |= ERR_WARN;
5918 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005919 }
Willy Tarreau93893792009-07-23 13:19:11 +02005920 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005921 }
5922 }
5923 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005924
Willy Tarreau6daf3432008-01-22 16:44:08 +01005925 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005926 err_code |= ERR_ALERT | ERR_FATAL;
5927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005928 }
Willy Tarreau93893792009-07-23 13:19:11 +02005929 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005930 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005931 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005932}
5933
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005934int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005935cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
5936{
5937#ifdef CONFIG_HAP_NS
5938 const char *err;
5939 const char *item = args[0];
5940
5941 if (!strcmp(item, "namespace_list")) {
5942 return 0;
5943 }
5944 else if (!strcmp(item, "namespace")) {
5945 size_t idx = 1;
5946 const char *current;
5947 while (*(current = args[idx++])) {
5948 err = invalid_char(current);
5949 if (err) {
5950 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5951 file, linenum, *err, item, current);
5952 return ERR_ALERT | ERR_FATAL;
5953 }
5954
5955 if (netns_store_lookup(current, strlen(current))) {
5956 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
5957 file, linenum, current);
5958 return ERR_ALERT | ERR_FATAL;
5959 }
5960 if (!netns_store_insert(current)) {
5961 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
5962 file, linenum, current);
5963 return ERR_ALERT | ERR_FATAL;
5964 }
5965 }
5966 }
5967
5968 return 0;
5969#else
5970 Alert("parsing [%s:%d]: namespace support is not compiled in.",
5971 file, linenum);
5972 return ERR_ALERT | ERR_FATAL;
5973#endif
5974}
5975
5976int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005977cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5978{
5979
5980 int err_code = 0;
5981 const char *err;
5982
5983 if (!strcmp(args[0], "userlist")) { /* new userlist */
5984 struct userlist *newul;
5985
5986 if (!*args[1]) {
5987 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5988 file, linenum, args[0]);
5989 err_code |= ERR_ALERT | ERR_FATAL;
5990 goto out;
5991 }
5992
5993 err = invalid_char(args[1]);
5994 if (err) {
5995 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5996 file, linenum, *err, args[0], args[1]);
5997 err_code |= ERR_ALERT | ERR_FATAL;
5998 goto out;
5999 }
6000
6001 for (newul = userlist; newul; newul = newul->next)
6002 if (!strcmp(newul->name, args[1])) {
6003 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6004 file, linenum, args[1]);
6005 err_code |= ERR_WARN;
6006 goto out;
6007 }
6008
6009 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6010 if (!newul) {
6011 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6012 err_code |= ERR_ALERT | ERR_ABORT;
6013 goto out;
6014 }
6015
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006016 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006017 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006018 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6019 err_code |= ERR_ALERT | ERR_ABORT;
6020 goto out;
6021 }
6022
6023 newul->next = userlist;
6024 userlist = newul;
6025
6026 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006027 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006028 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006029 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006030
6031 if (!*args[1]) {
6032 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6033 file, linenum, args[0]);
6034 err_code |= ERR_ALERT | ERR_FATAL;
6035 goto out;
6036 }
6037
6038 err = invalid_char(args[1]);
6039 if (err) {
6040 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6041 file, linenum, *err, args[0], args[1]);
6042 err_code |= ERR_ALERT | ERR_FATAL;
6043 goto out;
6044 }
6045
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006046 for (ag = userlist->groups; ag; ag = ag->next)
6047 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006048 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6049 file, linenum, args[1], userlist->name);
6050 err_code |= ERR_ALERT;
6051 goto out;
6052 }
6053
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006054 ag = calloc(1, sizeof(*ag));
6055 if (!ag) {
6056 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6057 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006058 goto out;
6059 }
6060
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006061 ag->name = strdup(args[1]);
6062 if (!ag) {
6063 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6064 err_code |= ERR_ALERT | ERR_ABORT;
6065 goto out;
6066 }
6067
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006068 cur_arg = 2;
6069
6070 while (*args[cur_arg]) {
6071 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006072 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006073 cur_arg += 2;
6074 continue;
6075 } else {
6076 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6077 file, linenum, args[0]);
6078 err_code |= ERR_ALERT | ERR_FATAL;
6079 goto out;
6080 }
6081 }
6082
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006083 ag->next = userlist->groups;
6084 userlist->groups = ag;
6085
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006086 } else if (!strcmp(args[0], "user")) { /* new user */
6087 struct auth_users *newuser;
6088 int cur_arg;
6089
6090 if (!*args[1]) {
6091 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6092 file, linenum, args[0]);
6093 err_code |= ERR_ALERT | ERR_FATAL;
6094 goto out;
6095 }
6096
6097 for (newuser = userlist->users; newuser; newuser = newuser->next)
6098 if (!strcmp(newuser->user, args[1])) {
6099 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6100 file, linenum, args[1], userlist->name);
6101 err_code |= ERR_ALERT;
6102 goto out;
6103 }
6104
6105 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6106 if (!newuser) {
6107 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6108 err_code |= ERR_ALERT | ERR_ABORT;
6109 goto out;
6110 }
6111
6112 newuser->user = strdup(args[1]);
6113
6114 newuser->next = userlist->users;
6115 userlist->users = newuser;
6116
6117 cur_arg = 2;
6118
6119 while (*args[cur_arg]) {
6120 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006121#ifdef CONFIG_HAP_CRYPT
6122 if (!crypt("", args[cur_arg + 1])) {
6123 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6124 file, linenum, newuser->user);
6125 err_code |= ERR_ALERT | ERR_FATAL;
6126 goto out;
6127 }
6128#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006129 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6130 file, linenum);
6131 err_code |= ERR_ALERT;
6132#endif
6133 newuser->pass = strdup(args[cur_arg + 1]);
6134 cur_arg += 2;
6135 continue;
6136 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6137 newuser->pass = strdup(args[cur_arg + 1]);
6138 newuser->flags |= AU_O_INSECURE;
6139 cur_arg += 2;
6140 continue;
6141 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006142 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006143 cur_arg += 2;
6144 continue;
6145 } else {
6146 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6147 file, linenum, args[0]);
6148 err_code |= ERR_ALERT | ERR_FATAL;
6149 goto out;
6150 }
6151 }
6152 } else {
6153 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6154 err_code |= ERR_ALERT | ERR_FATAL;
6155 }
6156
6157out:
6158 return err_code;
6159}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006160
6161/*
6162 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006163 * Returns the error code, 0 if OK, or any combination of :
6164 * - ERR_ABORT: must abort ASAP
6165 * - ERR_FATAL: we can continue parsing but not start the service
6166 * - ERR_WARN: a warning has been emitted
6167 * - ERR_ALERT: an alert has been emitted
6168 * Only the two first ones can stop processing, the two others are just
6169 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006170 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006171int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006172{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006173 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006174 FILE *f;
6175 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006176 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006177 struct cfg_section *cs = NULL;
6178 struct cfg_section *ics;
6179
6180 /* Register internal sections */
6181 if (!cfg_register_section("listen", cfg_parse_listen) ||
6182 !cfg_register_section("frontend", cfg_parse_listen) ||
6183 !cfg_register_section("backend", cfg_parse_listen) ||
6184 !cfg_register_section("ruleset", cfg_parse_listen) ||
6185 !cfg_register_section("defaults", cfg_parse_listen) ||
6186 !cfg_register_section("global", cfg_parse_global) ||
6187 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006188 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006189 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006190 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006191 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006192
Willy Tarreaubaaee002006-06-26 02:48:02 +02006193 if ((f=fopen(file,"r")) == NULL)
6194 return -1;
6195
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006196 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006197 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006198 char *end;
6199 char *args[MAX_LINE_ARGS + 1];
6200 char *line = thisline;
6201
Willy Tarreaubaaee002006-06-26 02:48:02 +02006202 linenum++;
6203
6204 end = line + strlen(line);
6205
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006206 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6207 /* Check if we reached the limit and the last char is not \n.
6208 * Watch out for the last line without the terminating '\n'!
6209 */
6210 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006211 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006212 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006213 }
6214
Willy Tarreaubaaee002006-06-26 02:48:02 +02006215 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006216 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006217 line++;
6218
6219 arg = 0;
6220 args[arg] = line;
6221
6222 while (*line && arg < MAX_LINE_ARGS) {
6223 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6224 * C equivalent value. Other combinations left unchanged (eg: \1).
6225 */
6226 if (*line == '\\') {
6227 int skip = 0;
6228 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6229 *line = line[1];
6230 skip = 1;
6231 }
6232 else if (line[1] == 'r') {
6233 *line = '\r';
6234 skip = 1;
6235 }
6236 else if (line[1] == 'n') {
6237 *line = '\n';
6238 skip = 1;
6239 }
6240 else if (line[1] == 't') {
6241 *line = '\t';
6242 skip = 1;
6243 }
6244 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006245 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006246 unsigned char hex1, hex2;
6247 hex1 = toupper(line[2]) - '0';
6248 hex2 = toupper(line[3]) - '0';
6249 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6250 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6251 *line = (hex1<<4) + hex2;
6252 skip = 3;
6253 }
6254 else {
6255 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006256 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006257 }
6258 }
6259 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006260 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006261 end -= skip;
6262 }
6263 line++;
6264 }
6265 else if (*line == '#' || *line == '\n' || *line == '\r') {
6266 /* end of string, end of loop */
6267 *line = 0;
6268 break;
6269 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006270 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006271 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006272 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006273 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006274 line++;
6275 args[++arg] = line;
6276 }
6277 else {
6278 line++;
6279 }
6280 }
6281
6282 /* empty line */
6283 if (!**args)
6284 continue;
6285
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006286 if (*line) {
6287 /* we had to stop due to too many args.
6288 * Let's terminate the string, print the offending part then cut the
6289 * last arg.
6290 */
6291 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6292 line++;
6293 *line = '\0';
6294
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006295 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006296 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006297 err_code |= ERR_ALERT | ERR_FATAL;
6298 args[arg] = line;
6299 }
6300
Willy Tarreau540abe42007-05-02 20:50:16 +02006301 /* zero out remaining args and ensure that at least one entry
6302 * is zeroed out.
6303 */
6304 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006305 args[arg] = line;
6306 }
6307
Willy Tarreau3842f002009-06-14 11:39:52 +02006308 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006309 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006310 char *tmp;
6311
Willy Tarreau3842f002009-06-14 11:39:52 +02006312 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006313 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006314 for (arg=0; *args[arg+1]; arg++)
6315 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006316 *tmp = '\0'; // fix the next arg to \0
6317 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006318 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006319 else if (!strcmp(args[0], "default")) {
6320 kwm = KWM_DEF;
6321 for (arg=0; *args[arg+1]; arg++)
6322 args[arg] = args[arg+1]; // shift args after inversion
6323 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006324
William Lallemand0f99e342011-10-12 17:50:54 +02006325 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6326 strcmp(args[0], "log") != 0) {
6327 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006328 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006329 }
6330
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006331 /* detect section start */
6332 list_for_each_entry(ics, &sections, list) {
6333 if (strcmp(args[0], ics->section_name) == 0) {
6334 cursection = ics->section_name;
6335 cs = ics;
6336 break;
6337 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006338 }
6339
Willy Tarreaubaaee002006-06-26 02:48:02 +02006340 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006341 if (cs)
6342 err_code |= cs->section_parser(file, linenum, args, kwm);
6343 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006344 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006345 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006346 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006347
6348 if (err_code & ERR_ABORT)
6349 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006350 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006351 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006352 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006353 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006354}
6355
Willy Tarreau64ab6072014-09-16 12:17:36 +02006356/* This function propagates processes from frontend <from> to backend <to> so
6357 * that it is always guaranteed that a backend pointed to by a frontend is
6358 * bound to all of its processes. After that, if the target is a "listen"
6359 * instance, the function recursively descends the target's own targets along
6360 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6361 * checked first to ensure that <to> is already bound to all processes of
6362 * <from>, there is no risk of looping and we ensure to follow the shortest
6363 * path to the destination.
6364 *
6365 * It is possible to set <to> to NULL for the first call so that the function
6366 * takes care of visiting the initial frontend in <from>.
6367 *
6368 * It is important to note that the function relies on the fact that all names
6369 * have already been resolved.
6370 */
6371void propagate_processes(struct proxy *from, struct proxy *to)
6372{
6373 struct switching_rule *rule;
6374 struct hdr_exp *exp;
6375
6376 if (to) {
6377 /* check whether we need to go down */
6378 if (from->bind_proc &&
6379 (from->bind_proc & to->bind_proc) == from->bind_proc)
6380 return;
6381
6382 if (!from->bind_proc && !to->bind_proc)
6383 return;
6384
6385 to->bind_proc = from->bind_proc ?
6386 (to->bind_proc | from->bind_proc) : 0;
6387
6388 /* now propagate down */
6389 from = to;
6390 }
6391
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006392 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006393 return;
6394
Willy Tarreauf6b70012014-12-18 14:00:43 +01006395 if (from->state == PR_STSTOPPED)
6396 return;
6397
Willy Tarreau64ab6072014-09-16 12:17:36 +02006398 /* default_backend */
6399 if (from->defbe.be)
6400 propagate_processes(from, from->defbe.be);
6401
6402 /* use_backend */
6403 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006404 if (rule->dynamic)
6405 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006406 to = rule->be.backend;
6407 propagate_processes(from, to);
6408 }
6409
6410 /* reqsetbe */
6411 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6412 if (exp->action != ACT_SETBE)
6413 continue;
6414 to = (struct proxy *)exp->replace;
6415 propagate_processes(from, to);
6416 }
6417}
6418
Willy Tarreaubb925012009-07-23 13:36:36 +02006419/*
6420 * Returns the error code, 0 if OK, or any combination of :
6421 * - ERR_ABORT: must abort ASAP
6422 * - ERR_FATAL: we can continue parsing but not start the service
6423 * - ERR_WARN: a warning has been emitted
6424 * - ERR_ALERT: an alert has been emitted
6425 * Only the two first ones can stop processing, the two others are just
6426 * indicators.
6427 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006428int check_config_validity()
6429{
6430 int cfgerr = 0;
6431 struct proxy *curproxy = NULL;
6432 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006433 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006434 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006435 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006436
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006437 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006438 /*
6439 * Now, check for the integrity of all that we have collected.
6440 */
6441
6442 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006443 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006444
Willy Tarreau193b8c62012-11-22 00:17:38 +01006445 if (!global.tune.max_http_hdr)
6446 global.tune.max_http_hdr = MAX_HTTP_HDR;
6447
6448 if (!global.tune.cookie_len)
6449 global.tune.cookie_len = CAPTURE_LEN;
6450
6451 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6452
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006453 /* Post initialisation of the users and groups lists. */
6454 err_code = userlist_postinit();
6455 if (err_code != ERR_NONE)
6456 goto out;
6457
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006458 /* first, we will invert the proxy list order */
6459 curproxy = NULL;
6460 while (proxy) {
6461 struct proxy *next;
6462
6463 next = proxy->next;
6464 proxy->next = curproxy;
6465 curproxy = proxy;
6466 if (!next)
6467 break;
6468 proxy = next;
6469 }
6470
Willy Tarreau419ead82014-09-16 13:41:21 +02006471 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006472 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006473 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006474 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006475 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006476 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006477 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006478 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006479
Willy Tarreau050536d2012-10-04 08:47:34 +02006480 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006481 /* proxy ID not set, use automatic numbering with first
6482 * spare entry starting with next_pxid.
6483 */
6484 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6485 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6486 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006487 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006488 next_pxid++;
6489
Willy Tarreau55ea7572007-06-17 19:56:27 +02006490
Willy Tarreaubaaee002006-06-26 02:48:02 +02006491 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006492 /* ensure we don't keep listeners uselessly bound */
6493 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006494 continue;
6495 }
6496
Willy Tarreau102df612014-05-07 23:56:38 +02006497 /* Check multi-process mode compatibility for the current proxy */
6498
6499 if (curproxy->bind_proc) {
6500 /* an explicit bind-process was specified, let's check how many
6501 * processes remain.
6502 */
6503 nbproc = popcount(curproxy->bind_proc);
6504
6505 curproxy->bind_proc &= nbits(global.nbproc);
6506 if (!curproxy->bind_proc && nbproc == 1) {
6507 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);
6508 curproxy->bind_proc = 1;
6509 }
6510 else if (!curproxy->bind_proc && nbproc > 1) {
6511 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);
6512 curproxy->bind_proc = 0;
6513 }
6514 }
6515
Willy Tarreau3d209582014-05-09 17:06:11 +02006516 /* check and reduce the bind-proc of each listener */
6517 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6518 unsigned long mask;
6519
6520 if (!bind_conf->bind_proc)
6521 continue;
6522
6523 mask = nbits(global.nbproc);
6524 if (curproxy->bind_proc)
6525 mask &= curproxy->bind_proc;
6526 /* mask cannot be null here thanks to the previous checks */
6527
6528 nbproc = popcount(bind_conf->bind_proc);
6529 bind_conf->bind_proc &= mask;
6530
6531 if (!bind_conf->bind_proc && nbproc == 1) {
6532 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",
6533 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6534 bind_conf->bind_proc = mask & ~(mask - 1);
6535 }
6536 else if (!bind_conf->bind_proc && nbproc > 1) {
6537 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",
6538 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6539 bind_conf->bind_proc = 0;
6540 }
6541 }
6542
Willy Tarreau102df612014-05-07 23:56:38 +02006543 if (global.nbproc > 1 && curproxy->table.peers.name) {
6544 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6545 curproxy->id);
6546 cfgerr++;
6547 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006548
Willy Tarreauff01a212009-03-15 13:46:16 +01006549 switch (curproxy->mode) {
6550 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006551 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006552 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006553 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6554 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006555 cfgerr++;
6556 }
6557
6558 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006559 Warning("config : servers will be ignored for %s '%s'.\n",
6560 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006561 break;
6562
6563 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006564 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006565 break;
6566
6567 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006568 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006569 break;
6570 }
6571
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006572 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006573 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006574 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006575 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6576 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006577 cfgerr++;
6578 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006579#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006580 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006581 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6582 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006583 cfgerr++;
6584 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006585#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006586 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006587 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6588 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006589 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006590 }
6591 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006592 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006593 /* If no LB algo is set in a backend, and we're not in
6594 * transparent mode, dispatch mode nor proxy mode, we
6595 * want to use balance roundrobin by default.
6596 */
6597 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6598 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006599 }
6600 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006601
Willy Tarreau1620ec32011-08-06 17:05:02 +02006602 if (curproxy->options & PR_O_DISPATCH)
6603 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6604 else if (curproxy->options & PR_O_HTTP_PROXY)
6605 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6606 else if (curproxy->options & PR_O_TRANSP)
6607 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006608
Willy Tarreau1620ec32011-08-06 17:05:02 +02006609 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6610 if (curproxy->options & PR_O_DISABLE404) {
6611 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6612 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6613 err_code |= ERR_WARN;
6614 curproxy->options &= ~PR_O_DISABLE404;
6615 }
6616 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6617 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6618 "send-state", proxy_type_str(curproxy), curproxy->id);
6619 err_code |= ERR_WARN;
6620 curproxy->options &= ~PR_O2_CHK_SNDST;
6621 }
Willy Tarreauef781042010-01-27 11:53:01 +01006622 }
6623
Simon Horman98637e52014-06-20 12:30:16 +09006624 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6625 if (!global.external_check) {
6626 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6627 curproxy->id, "option external-check");
6628 cfgerr++;
6629 }
6630 if (!curproxy->check_command) {
6631 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6632 curproxy->id, "option external-check");
6633 cfgerr++;
6634 }
6635 }
6636
Simon Horman64e34162015-02-06 11:11:57 +09006637 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006638 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
6639 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09006640 "'email-alert from', 'email-alert level' 'email-alert mailer', "
6641 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006642 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
6643 "to be present).\n",
6644 proxy_type_str(curproxy), curproxy->id);
6645 err_code |= ERR_WARN;
6646 free_email_alert(curproxy);
6647 }
6648 if (!curproxy->email_alert.myhostname)
6649 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09006650 }
6651
Simon Horman98637e52014-06-20 12:30:16 +09006652 if (curproxy->check_command) {
6653 int clear = 0;
6654 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6655 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6656 "external-check command", proxy_type_str(curproxy), curproxy->id);
6657 err_code |= ERR_WARN;
6658 clear = 1;
6659 }
6660 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6661 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6662 curproxy->id, "external-check command");
6663 cfgerr++;
6664 }
6665 if (clear) {
6666 free(curproxy->check_command);
6667 curproxy->check_command = NULL;
6668 }
6669 }
6670
6671 if (curproxy->check_path) {
6672 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6673 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6674 "external-check path", proxy_type_str(curproxy), curproxy->id);
6675 err_code |= ERR_WARN;
6676 free(curproxy->check_path);
6677 curproxy->check_path = NULL;
6678 }
6679 }
6680
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006681 /* if a default backend was specified, let's find it */
6682 if (curproxy->defbe.name) {
6683 struct proxy *target;
6684
Alex Williams96532db2009-11-01 21:27:13 -05006685 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006686 if (!target) {
6687 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6688 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006689 cfgerr++;
6690 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006691 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6692 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006693 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006694 } else {
6695 free(curproxy->defbe.name);
6696 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006697
6698 /* Emit a warning if this proxy also has some servers */
6699 if (curproxy->srv) {
6700 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6701 curproxy->id);
6702 err_code |= ERR_WARN;
6703 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006704 }
6705 }
6706
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006707 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006708 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6709 /* map jump target for ACT_SETBE in req_rep chain */
6710 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006711 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006712 struct proxy *target;
6713
Willy Tarreaua496b602006-12-17 23:15:24 +01006714 if (exp->action != ACT_SETBE)
6715 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006716
Alex Williams96532db2009-11-01 21:27:13 -05006717 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006718 if (!target) {
6719 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6720 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006721 cfgerr++;
6722 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006723 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6724 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006725 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006726 } else {
6727 free((void *)exp->replace);
6728 exp->replace = (const char *)target;
6729 }
6730 }
6731 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006732
6733 /* find the target proxy for 'use_backend' rules */
6734 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006735 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006736 struct logformat_node *node;
6737 char *pxname;
6738
6739 /* Try to parse the string as a log format expression. If the result
6740 * of the parsing is only one entry containing a simple string, then
6741 * it's a standard string corresponding to a static rule, thus the
6742 * parsing is cancelled and be.name is restored to be resolved.
6743 */
6744 pxname = rule->be.name;
6745 LIST_INIT(&rule->be.expr);
6746 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6747 curproxy->conf.args.file, curproxy->conf.args.line);
6748 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6749
6750 if (!LIST_ISEMPTY(&rule->be.expr)) {
6751 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6752 rule->dynamic = 1;
6753 free(pxname);
6754 continue;
6755 }
6756 /* simple string: free the expression and fall back to static rule */
6757 free(node->arg);
6758 free(node);
6759 }
6760
6761 rule->dynamic = 0;
6762 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006763
Alex Williams96532db2009-11-01 21:27:13 -05006764 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006765
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006766 if (!target) {
6767 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6768 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006769 cfgerr++;
6770 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006771 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6772 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006773 cfgerr++;
6774 } else {
6775 free((void *)rule->be.name);
6776 rule->be.backend = target;
6777 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006778 }
6779
Willy Tarreau64ab6072014-09-16 12:17:36 +02006780 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006781 list_for_each_entry(srule, &curproxy->server_rules, list) {
6782 struct server *target = findserver(curproxy, srule->srv.name);
6783
6784 if (!target) {
6785 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6786 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6787 cfgerr++;
6788 continue;
6789 }
6790 free((void *)srule->srv.name);
6791 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006792 }
6793
Emeric Brunb982a3d2010-01-04 15:45:53 +01006794 /* find the target table for 'stick' rules */
6795 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6796 struct proxy *target;
6797
Emeric Brun1d33b292010-01-04 15:47:17 +01006798 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6799 if (mrule->flags & STK_IS_STORE)
6800 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6801
Emeric Brunb982a3d2010-01-04 15:45:53 +01006802 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006803 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006804 else
6805 target = curproxy;
6806
6807 if (!target) {
6808 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6809 curproxy->id, mrule->table.name);
6810 cfgerr++;
6811 }
6812 else if (target->table.size == 0) {
6813 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6814 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6815 cfgerr++;
6816 }
Willy Tarreau12785782012-04-27 21:37:17 +02006817 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6818 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006819 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6820 cfgerr++;
6821 }
6822 else {
6823 free((void *)mrule->table.name);
6824 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006825 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006826 }
6827 }
6828
6829 /* find the target table for 'store response' rules */
6830 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6831 struct proxy *target;
6832
Emeric Brun1d33b292010-01-04 15:47:17 +01006833 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6834
Emeric Brunb982a3d2010-01-04 15:45:53 +01006835 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006836 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006837 else
6838 target = curproxy;
6839
6840 if (!target) {
6841 Alert("Proxy '%s': unable to find store table '%s'.\n",
6842 curproxy->id, mrule->table.name);
6843 cfgerr++;
6844 }
6845 else if (target->table.size == 0) {
6846 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6847 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6848 cfgerr++;
6849 }
Willy Tarreau12785782012-04-27 21:37:17 +02006850 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6851 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006852 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6853 cfgerr++;
6854 }
6855 else {
6856 free((void *)mrule->table.name);
6857 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006858 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006859 }
6860 }
6861
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006862 /* find the target table for 'tcp-request' layer 4 rules */
6863 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6864 struct proxy *target;
6865
Willy Tarreaub4c84932013-07-23 19:15:30 +02006866 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006867 continue;
6868
6869 if (trule->act_prm.trk_ctr.table.n)
6870 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6871 else
6872 target = curproxy;
6873
6874 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006875 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6876 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006877 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006878 cfgerr++;
6879 }
6880 else if (target->table.size == 0) {
6881 Alert("Proxy '%s': table '%s' used but not configured.\n",
6882 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6883 cfgerr++;
6884 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006885 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6886 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6887 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 +01006888 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006889 cfgerr++;
6890 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006891 else {
6892 free(trule->act_prm.trk_ctr.table.n);
6893 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006894 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006895 * to pass a list of counters to track and allocate them right here using
6896 * stktable_alloc_data_type().
6897 */
6898 }
6899 }
6900
Willy Tarreaud1f96522010-08-03 19:34:32 +02006901 /* find the target table for 'tcp-request' layer 6 rules */
6902 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6903 struct proxy *target;
6904
Willy Tarreaub4c84932013-07-23 19:15:30 +02006905 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006906 continue;
6907
6908 if (trule->act_prm.trk_ctr.table.n)
6909 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6910 else
6911 target = curproxy;
6912
6913 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006914 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6915 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006916 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006917 cfgerr++;
6918 }
6919 else if (target->table.size == 0) {
6920 Alert("Proxy '%s': table '%s' used but not configured.\n",
6921 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6922 cfgerr++;
6923 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006924 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6925 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6926 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 +01006927 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006928 cfgerr++;
6929 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006930 else {
6931 free(trule->act_prm.trk_ctr.table.n);
6932 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006933 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006934 * to pass a list of counters to track and allocate them right here using
6935 * stktable_alloc_data_type().
6936 */
6937 }
6938 }
6939
Willy Tarreau09448f72014-06-25 18:12:15 +02006940 /* find the target table for 'http-request' layer 7 rules */
6941 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6942 struct proxy *target;
6943
6944 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6945 continue;
6946
6947 if (hrqrule->act_prm.trk_ctr.table.n)
6948 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6949 else
6950 target = curproxy;
6951
6952 if (!target) {
6953 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6954 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6955 http_req_trk_idx(hrqrule->action));
6956 cfgerr++;
6957 }
6958 else if (target->table.size == 0) {
6959 Alert("Proxy '%s': table '%s' used but not configured.\n",
6960 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6961 cfgerr++;
6962 }
6963 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6964 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6965 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6966 http_req_trk_idx(hrqrule->action));
6967 cfgerr++;
6968 }
6969 else {
6970 free(hrqrule->act_prm.trk_ctr.table.n);
6971 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6972 /* Note: if we decide to enhance the track-sc syntax, we may be able
6973 * to pass a list of counters to track and allocate them right here using
6974 * stktable_alloc_data_type().
6975 */
6976 }
6977 }
6978
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006979 /* move any "block" rules at the beginning of the http-request rules */
6980 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6981 /* insert block_rules into http_req_rules at the beginning */
6982 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6983 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6984 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6985 curproxy->http_req_rules.n = curproxy->block_rules.n;
6986 LIST_INIT(&curproxy->block_rules);
6987 }
6988
Emeric Brun32da3c42010-09-23 18:39:19 +02006989 if (curproxy->table.peers.name) {
6990 struct peers *curpeers = peers;
6991
6992 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6993 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6994 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006995 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006996 break;
6997 }
6998 }
6999
7000 if (!curpeers) {
7001 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7002 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007003 free((void *)curproxy->table.peers.name);
7004 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007005 cfgerr++;
7006 }
7007 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007008 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7009 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007010 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007011 cfgerr++;
7012 }
7013 }
7014
Simon Horman9dc49962015-01-30 11:22:59 +09007015
7016 if (curproxy->email_alert.mailers.name) {
7017 struct mailers *curmailers = mailers;
7018
7019 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7020 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7021 free(curproxy->email_alert.mailers.name);
7022 curproxy->email_alert.mailers.m = curmailers;
7023 curmailers->users++;
7024 break;
7025 }
7026 }
7027
7028 if (!curmailers) {
7029 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7030 curproxy->id, curproxy->email_alert.mailers.name);
7031 free_email_alert(curproxy);
7032 cfgerr++;
7033 }
7034 }
7035
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007036 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007037 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007038 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7039 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7040 "proxy", curproxy->id);
7041 cfgerr++;
7042 goto out_uri_auth_compat;
7043 }
7044
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007045 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007046 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007047 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007048 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007049
Willy Tarreau95fa4692010-02-01 13:05:50 +01007050 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7051 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007052
7053 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007054 uri_auth_compat_req[i++] = "realm";
7055 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7056 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007057
Willy Tarreau95fa4692010-02-01 13:05:50 +01007058 uri_auth_compat_req[i++] = "unless";
7059 uri_auth_compat_req[i++] = "{";
7060 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7061 uri_auth_compat_req[i++] = "}";
7062 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007063
Willy Tarreauff011f22011-01-06 17:51:27 +01007064 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7065 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007066 cfgerr++;
7067 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007068 }
7069
Willy Tarreauff011f22011-01-06 17:51:27 +01007070 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007071
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007072 if (curproxy->uri_auth->auth_realm) {
7073 free(curproxy->uri_auth->auth_realm);
7074 curproxy->uri_auth->auth_realm = NULL;
7075 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007076
7077 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007078 }
7079out_uri_auth_compat:
7080
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007081 /* compile the log format */
7082 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007083 if (curproxy->conf.logformat_string != default_http_log_format &&
7084 curproxy->conf.logformat_string != default_tcp_log_format &&
7085 curproxy->conf.logformat_string != clf_http_log_format)
7086 free(curproxy->conf.logformat_string);
7087 curproxy->conf.logformat_string = NULL;
7088 free(curproxy->conf.lfs_file);
7089 curproxy->conf.lfs_file = NULL;
7090 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007091 }
7092
Willy Tarreau62a61232013-04-12 18:13:46 +02007093 if (curproxy->conf.logformat_string) {
7094 curproxy->conf.args.ctx = ARGC_LOG;
7095 curproxy->conf.args.file = curproxy->conf.lfs_file;
7096 curproxy->conf.args.line = curproxy->conf.lfs_line;
7097 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007098 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007099 curproxy->conf.args.file = NULL;
7100 curproxy->conf.args.line = 0;
7101 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007102
Willy Tarreau62a61232013-04-12 18:13:46 +02007103 if (curproxy->conf.uniqueid_format_string) {
7104 curproxy->conf.args.ctx = ARGC_UIF;
7105 curproxy->conf.args.file = curproxy->conf.uif_file;
7106 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007107 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007108 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007109 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007110 curproxy->conf.args.file = NULL;
7111 curproxy->conf.args.line = 0;
7112 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007113
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007114 /* only now we can check if some args remain unresolved.
7115 * This must be done after the users and groups resolution.
7116 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007117 cfgerr += smp_resolve_args(curproxy);
7118 if (!cfgerr)
7119 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007120
Willy Tarreau2738a142006-07-08 17:28:09 +02007121 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007122 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007123 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007124 (!curproxy->timeout.connect ||
7125 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007126 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007127 " | While not properly invalid, you will certainly encounter various problems\n"
7128 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007129 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007130 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007131 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007132 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007133
Willy Tarreau1fa31262007-12-03 00:36:16 +01007134 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7135 * We must still support older configurations, so let's find out whether those
7136 * parameters have been set or must be copied from contimeouts.
7137 */
7138 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007139 if (!curproxy->timeout.tarpit ||
7140 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007141 /* tarpit timeout not set. We search in the following order:
7142 * default.tarpit, curr.connect, default.connect.
7143 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007144 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007145 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007146 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007147 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007148 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007149 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007150 }
7151 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007152 (!curproxy->timeout.queue ||
7153 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007154 /* queue timeout not set. We search in the following order:
7155 * default.queue, curr.connect, default.connect.
7156 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007157 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007158 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007159 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007160 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007161 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007162 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007163 }
7164 }
7165
Willy Tarreau1620ec32011-08-06 17:05:02 +02007166 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007167 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7168 curproxy->check_req = (char *)malloc(curproxy->check_len);
7169 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007170 }
7171
Willy Tarreau215663d2014-06-13 18:30:23 +02007172 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7173 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7174 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7175 proxy_type_str(curproxy), curproxy->id);
7176 err_code |= ERR_WARN;
7177 }
7178
Willy Tarreau193b8c62012-11-22 00:17:38 +01007179 /* ensure that cookie capture length is not too large */
7180 if (curproxy->capture_len >= global.tune.cookie_len) {
7181 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7182 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7183 err_code |= ERR_WARN;
7184 curproxy->capture_len = global.tune.cookie_len - 1;
7185 }
7186
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007187 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007188 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007189 curproxy->req_cap_pool = create_pool("ptrcap",
7190 curproxy->nb_req_cap * sizeof(char *),
7191 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007192 }
7193
7194 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007195 curproxy->rsp_cap_pool = create_pool("ptrcap",
7196 curproxy->nb_rsp_cap * sizeof(char *),
7197 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007198 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007199
Willy Tarreaubaaee002006-06-26 02:48:02 +02007200 /* first, we will invert the servers list order */
7201 newsrv = NULL;
7202 while (curproxy->srv) {
7203 struct server *next;
7204
7205 next = curproxy->srv->next;
7206 curproxy->srv->next = newsrv;
7207 newsrv = curproxy->srv;
7208 if (!next)
7209 break;
7210 curproxy->srv = next;
7211 }
7212
Willy Tarreau17edc812014-01-03 12:14:34 +01007213 /* Check that no server name conflicts. This causes trouble in the stats.
7214 * We only emit a warning for the first conflict affecting each server,
7215 * in order to avoid combinatory explosion if all servers have the same
7216 * name. We do that only for servers which do not have an explicit ID,
7217 * because these IDs were made also for distinguishing them and we don't
7218 * want to annoy people who correctly manage them.
7219 */
7220 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7221 struct server *other_srv;
7222
7223 if (newsrv->puid)
7224 continue;
7225
7226 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7227 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7228 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7229 newsrv->conf.file, newsrv->conf.line,
7230 proxy_type_str(curproxy), curproxy->id,
7231 newsrv->id, other_srv->conf.line);
7232 break;
7233 }
7234 }
7235 }
7236
Willy Tarreaudd701652010-05-25 23:03:02 +02007237 /* assign automatic UIDs to servers which don't have one yet */
7238 next_id = 1;
7239 newsrv = curproxy->srv;
7240 while (newsrv != NULL) {
7241 if (!newsrv->puid) {
7242 /* server ID not set, use automatic numbering with first
7243 * spare entry starting with next_svid.
7244 */
7245 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7246 newsrv->conf.id.key = newsrv->puid = next_id;
7247 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7248 }
7249 next_id++;
7250 newsrv = newsrv->next;
7251 }
7252
Willy Tarreau20697042007-11-15 23:26:18 +01007253 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007254 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007255
Willy Tarreau62c3be22012-01-20 13:12:32 +01007256 /*
7257 * If this server supports a maxconn parameter, it needs a dedicated
7258 * tasks to fill the emptied slots when a connection leaves.
7259 * Also, resolve deferred tracking dependency if needed.
7260 */
7261 newsrv = curproxy->srv;
7262 while (newsrv != NULL) {
7263 if (newsrv->minconn > newsrv->maxconn) {
7264 /* Only 'minconn' was specified, or it was higher than or equal
7265 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7266 * this will avoid further useless expensive computations.
7267 */
7268 newsrv->maxconn = newsrv->minconn;
7269 } else if (newsrv->maxconn && !newsrv->minconn) {
7270 /* minconn was not specified, so we set it to maxconn */
7271 newsrv->minconn = newsrv->maxconn;
7272 }
7273
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007274#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007275 if (newsrv->use_ssl || newsrv->check.use_ssl)
7276 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007277#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007278
Willy Tarreau2f075e92013-12-03 11:11:34 +01007279 /* set the check type on the server */
7280 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7281
Willy Tarreau62c3be22012-01-20 13:12:32 +01007282 if (newsrv->trackit) {
7283 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007284 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007285 char *pname, *sname;
7286
7287 pname = newsrv->trackit;
7288 sname = strrchr(pname, '/');
7289
7290 if (sname)
7291 *sname++ = '\0';
7292 else {
7293 sname = pname;
7294 pname = NULL;
7295 }
7296
7297 if (pname) {
7298 px = findproxy(pname, PR_CAP_BE);
7299 if (!px) {
7300 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7301 proxy_type_str(curproxy), curproxy->id,
7302 newsrv->id, pname);
7303 cfgerr++;
7304 goto next_srv;
7305 }
7306 } else
7307 px = curproxy;
7308
7309 srv = findserver(px, sname);
7310 if (!srv) {
7311 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7312 proxy_type_str(curproxy), curproxy->id,
7313 newsrv->id, sname);
7314 cfgerr++;
7315 goto next_srv;
7316 }
7317
Willy Tarreau32091232014-05-16 13:52:00 +02007318 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7319 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7320 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007321 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007322 "tracking as it does not have any check nor agent enabled.\n",
7323 proxy_type_str(curproxy), curproxy->id,
7324 newsrv->id, px->id, srv->id);
7325 cfgerr++;
7326 goto next_srv;
7327 }
7328
7329 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7330
7331 if (loop) {
7332 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7333 "belongs to a tracking chain looping back to %s/%s.\n",
7334 proxy_type_str(curproxy), curproxy->id,
7335 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007336 cfgerr++;
7337 goto next_srv;
7338 }
7339
7340 if (curproxy != px &&
7341 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7342 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7343 "tracking: disable-on-404 option inconsistency.\n",
7344 proxy_type_str(curproxy), curproxy->id,
7345 newsrv->id, px->id, srv->id);
7346 cfgerr++;
7347 goto next_srv;
7348 }
7349
7350 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007351 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007352 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007353 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007354 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007355 }
7356
7357 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007358 newsrv->tracknext = srv->trackers;
7359 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007360
7361 free(newsrv->trackit);
7362 newsrv->trackit = NULL;
7363 }
7364 next_srv:
7365 newsrv = newsrv->next;
7366 }
7367
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007368 /* We have to initialize the server lookup mechanism depending
7369 * on what LB algorithm was choosen.
7370 */
7371
7372 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7373 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7374 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007375 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7376 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7377 init_server_map(curproxy);
7378 } else {
7379 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7380 fwrr_init_server_groups(curproxy);
7381 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007382 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007383
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007384 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007385 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7386 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7387 fwlc_init_server_tree(curproxy);
7388 } else {
7389 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7390 fas_init_server_tree(curproxy);
7391 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007392 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007393
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007394 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007395 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7396 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7397 chash_init_server_tree(curproxy);
7398 } else {
7399 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7400 init_server_map(curproxy);
7401 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007402 break;
7403 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007404
7405 if (curproxy->options & PR_O_LOGASAP)
7406 curproxy->to_log &= ~LW_BYTES;
7407
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007408 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007409 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007410 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7411 proxy_type_str(curproxy), curproxy->id);
7412 err_code |= ERR_WARN;
7413 }
7414
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007415 if (curproxy->mode != PR_MODE_HTTP) {
7416 int optnum;
7417
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007418 if (curproxy->uri_auth) {
7419 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7420 proxy_type_str(curproxy), curproxy->id);
7421 err_code |= ERR_WARN;
7422 curproxy->uri_auth = NULL;
7423 }
7424
Willy Tarreau87cf5142011-08-19 22:57:24 +02007425 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007426 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7427 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7428 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007429 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007430 }
7431
7432 if (curproxy->options & PR_O_ORGTO) {
7433 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7434 "originalto", proxy_type_str(curproxy), curproxy->id);
7435 err_code |= ERR_WARN;
7436 curproxy->options &= ~PR_O_ORGTO;
7437 }
7438
7439 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7440 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7441 (curproxy->cap & cfg_opts[optnum].cap) &&
7442 (curproxy->options & cfg_opts[optnum].val)) {
7443 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7444 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7445 err_code |= ERR_WARN;
7446 curproxy->options &= ~cfg_opts[optnum].val;
7447 }
7448 }
7449
7450 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7451 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7452 (curproxy->cap & cfg_opts2[optnum].cap) &&
7453 (curproxy->options2 & cfg_opts2[optnum].val)) {
7454 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7455 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7456 err_code |= ERR_WARN;
7457 curproxy->options2 &= ~cfg_opts2[optnum].val;
7458 }
7459 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007460
Pieter Baauwd551fb52013-05-08 22:49:23 +02007461#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007462 if (curproxy->conn_src.bind_hdr_occ) {
7463 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007464 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007465 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007466 err_code |= ERR_WARN;
7467 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007468#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007469 }
7470
Willy Tarreaubaaee002006-06-26 02:48:02 +02007471 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007472 * ensure that we're not cross-dressing a TCP server into HTTP.
7473 */
7474 newsrv = curproxy->srv;
7475 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007476 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007477 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7478 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007479 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007480 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007481
Willy Tarreau0cec3312011-10-31 13:49:26 +01007482 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7483 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7484 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7485 err_code |= ERR_WARN;
7486 }
7487
Willy Tarreauc93cd162014-05-13 15:54:22 +02007488 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007489 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7490 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7491 err_code |= ERR_WARN;
7492 }
7493
Pieter Baauwd551fb52013-05-08 22:49:23 +02007494#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007495 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7496 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007497 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 +01007498 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007499 err_code |= ERR_WARN;
7500 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007501#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007502 newsrv = newsrv->next;
7503 }
7504
Willy Tarreaue42bd962014-09-16 16:21:19 +02007505 /* check if we have a frontend with "tcp-request content" looking at L7
7506 * with no inspect-delay
7507 */
7508 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7509 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7510 if (trule->action == TCP_ACT_CAPTURE &&
7511 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7512 break;
7513 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7514 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7515 break;
7516 }
7517
7518 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7519 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7520 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7521 " This means that these rules will randomly find their contents. This can be fixed by"
7522 " setting the tcp-request inspect-delay.\n",
7523 proxy_type_str(curproxy), curproxy->id);
7524 err_code |= ERR_WARN;
7525 }
7526 }
7527
Willy Tarreauc1a21672009-08-16 22:37:44 +02007528 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007529 if (!curproxy->accept)
7530 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007531
Willy Tarreauc1a21672009-08-16 22:37:44 +02007532 if (curproxy->tcp_req.inspect_delay ||
7533 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007534 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007535
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007536 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007537 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007538 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007539 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007540
7541 /* both TCP and HTTP must check switching rules */
7542 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7543 }
7544
7545 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007546 if (curproxy->tcp_req.inspect_delay ||
7547 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7548 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7549
Emeric Brun97679e72010-09-23 17:56:44 +02007550 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7551 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7552
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007553 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007554 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007555 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007556 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007557
7558 /* If the backend does requires RDP cookie persistence, we have to
7559 * enable the corresponding analyser.
7560 */
7561 if (curproxy->options2 & PR_O2_RDPC_PRST)
7562 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7563 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007564 }
7565
7566 /***********************************************************/
7567 /* At this point, target names have already been resolved. */
7568 /***********************************************************/
7569
7570 /* Check multi-process mode compatibility */
7571
7572 if (global.nbproc > 1 && global.stats_fe) {
7573 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7574 unsigned long mask;
7575
7576 mask = nbits(global.nbproc);
7577 if (global.stats_fe->bind_proc)
7578 mask &= global.stats_fe->bind_proc;
7579
7580 if (bind_conf->bind_proc)
7581 mask &= bind_conf->bind_proc;
7582
7583 /* stop here if more than one process is used */
7584 if (popcount(mask) > 1)
7585 break;
7586 }
7587 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7588 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");
7589 }
7590 }
7591
7592 /* Make each frontend inherit bind-process from its listeners when not specified. */
7593 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7594 if (curproxy->bind_proc)
7595 continue;
7596
7597 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7598 unsigned long mask;
7599
7600 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7601 curproxy->bind_proc |= mask;
7602 }
7603
7604 if (!curproxy->bind_proc)
7605 curproxy->bind_proc = ~0UL;
7606 }
7607
7608 if (global.stats_fe) {
7609 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7610 unsigned long mask;
7611
7612 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7613 global.stats_fe->bind_proc |= mask;
7614 }
7615 if (!global.stats_fe->bind_proc)
7616 global.stats_fe->bind_proc = ~0UL;
7617 }
7618
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007619 /* propagate bindings from frontends to backends. Don't do it if there
7620 * are any fatal errors as we must not call it with unresolved proxies.
7621 */
7622 if (!cfgerr) {
7623 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7624 if (curproxy->cap & PR_CAP_FE)
7625 propagate_processes(curproxy, NULL);
7626 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007627 }
7628
7629 /* Bind each unbound backend to all processes when not specified. */
7630 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7631 if (curproxy->bind_proc)
7632 continue;
7633 curproxy->bind_proc = ~0UL;
7634 }
7635
7636 /*******************************************************/
7637 /* At this step, all proxies have a non-null bind_proc */
7638 /*******************************************************/
7639
7640 /* perform the final checks before creating tasks */
7641
7642 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7643 struct listener *listener;
7644 unsigned int next_id;
7645 int nbproc;
7646
7647 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007648
Emeric Brunc52962f2012-11-15 18:28:02 +01007649#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007650 /* Configure SSL for each bind line.
7651 * Note: if configuration fails at some point, the ->ctx member
7652 * remains NULL so that listeners can later detach.
7653 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007654 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007655 int alloc_ctx;
7656
Emeric Brunc52962f2012-11-15 18:28:02 +01007657 if (!bind_conf->is_ssl) {
7658 if (bind_conf->default_ctx) {
7659 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7660 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7661 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007662 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007663 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007664 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007665 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007666 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007667 cfgerr++;
7668 continue;
7669 }
7670
Emeric Brun8dc60392014-05-09 13:52:00 +02007671 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007672 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007673 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7674 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");
7675 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007676 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007677 cfgerr++;
7678 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007679 }
7680
Emeric Brunfc0421f2012-09-07 17:30:07 +02007681 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007682 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007683 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007684#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007685
Willy Tarreaue6b98942007-10-29 01:09:36 +01007686 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007687 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007688 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007689 if (!listener->luid) {
7690 /* listener ID not set, use automatic numbering with first
7691 * spare entry starting with next_luid.
7692 */
7693 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7694 listener->conf.id.key = listener->luid = next_id;
7695 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007696 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007697 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007698
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007699 /* enable separate counters */
7700 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7701 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007702 if (!listener->name)
7703 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007704 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007705
Willy Tarreaue6b98942007-10-29 01:09:36 +01007706 if (curproxy->options & PR_O_TCP_NOLING)
7707 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007708 if (!listener->maxconn)
7709 listener->maxconn = curproxy->maxconn;
7710 if (!listener->backlog)
7711 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007712 if (!listener->maxaccept)
7713 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7714
7715 /* we want to have an optimal behaviour on single process mode to
7716 * maximize the work at once, but in multi-process we want to keep
7717 * some fairness between processes, so we target half of the max
7718 * number of events to be balanced over all the processes the proxy
7719 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7720 * used to disable the limit.
7721 */
7722 if (listener->maxaccept > 0) {
7723 if (nbproc > 1)
7724 listener->maxaccept = (listener->maxaccept + 1) / 2;
7725 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7726 }
7727
Willy Tarreau9903f0e2015-04-04 18:50:31 +02007728 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02007729 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007730 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01007731 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007732
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007733 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7734 listener->options |= LI_O_TCP_RULES;
7735
Willy Tarreaude3041d2010-05-31 10:56:17 +02007736 if (curproxy->mon_mask.s_addr)
7737 listener->options |= LI_O_CHK_MONNET;
7738
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007739 /* smart accept mode is automatic in HTTP mode */
7740 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007741 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007742 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7743 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007744 }
7745
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007746 /* Release unused SSL configs */
7747 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7748 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007749 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007750#ifdef USE_OPENSSL
7751 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007752 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007753 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007754 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007755 free(bind_conf->crl_file);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007756 free(bind_conf->tls_ticket_keys);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007757#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007758 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007759
Willy Tarreau102df612014-05-07 23:56:38 +02007760 if (nbproc > 1) {
7761 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02007762 int count, maxproc = 0;
7763
7764 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7765 count = popcount(bind_conf->bind_proc);
7766 if (count > maxproc)
7767 maxproc = count;
7768 }
7769 /* backends have 0, frontends have 1 or more */
7770 if (maxproc != 1)
7771 Warning("Proxy '%s': in multi-process mode, stats will be"
7772 " limited to process assigned to the current request.\n",
7773 curproxy->id);
7774
Willy Tarreau102df612014-05-07 23:56:38 +02007775 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7776 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7777 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007778 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007779 }
Willy Tarreau102df612014-05-07 23:56:38 +02007780 if (curproxy->appsession_name) {
7781 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7782 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007783 }
Willy Tarreau102df612014-05-07 23:56:38 +02007784 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7785 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7786 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007787 }
7788 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007789
7790 /* create the task associated with the proxy */
7791 curproxy->task = task_new();
7792 if (curproxy->task) {
7793 curproxy->task->context = curproxy;
7794 curproxy->task->process = manage_proxy;
7795 /* no need to queue, it will be done automatically if some
7796 * listener gets limited.
7797 */
7798 curproxy->task->expire = TICK_ETERNITY;
7799 } else {
7800 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7801 curproxy->id);
7802 cfgerr++;
7803 }
Willy Tarreaub369a042014-09-16 13:21:03 +02007804 }
7805
Willy Tarreaufbb78422011-06-05 15:38:35 +02007806 /* automatically compute fullconn if not set. We must not do it in the
7807 * loop above because cross-references are not yet fully resolved.
7808 */
7809 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7810 /* If <fullconn> is not set, let's set it to 10% of the sum of
7811 * the possible incoming frontend's maxconns.
7812 */
7813 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7814 struct proxy *fe;
7815 int total = 0;
7816
7817 /* sum up the number of maxconns of frontends which
7818 * reference this backend at least once or which are
7819 * the same one ('listen').
7820 */
7821 for (fe = proxy; fe; fe = fe->next) {
7822 struct switching_rule *rule;
7823 struct hdr_exp *exp;
7824 int found = 0;
7825
7826 if (!(fe->cap & PR_CAP_FE))
7827 continue;
7828
7829 if (fe == curproxy) /* we're on a "listen" instance */
7830 found = 1;
7831
7832 if (fe->defbe.be == curproxy) /* "default_backend" */
7833 found = 1;
7834
7835 /* check if a "use_backend" rule matches */
7836 if (!found) {
7837 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007838 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007839 found = 1;
7840 break;
7841 }
7842 }
7843 }
7844
7845 /* check if a "reqsetbe" rule matches */
7846 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7847 if (exp->action == ACT_SETBE &&
7848 (struct proxy *)exp->replace == curproxy) {
7849 found = 1;
7850 break;
7851 }
7852 }
7853
7854 /* now we've checked all possible ways to reference a backend
7855 * from a frontend.
7856 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007857 if (!found)
7858 continue;
7859 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007860 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007861 /* we have the sum of the maxconns in <total>. We only
7862 * keep 10% of that sum to set the default fullconn, with
7863 * a hard minimum of 1 (to avoid a divide by zero).
7864 */
7865 curproxy->fullconn = (total + 9) / 10;
7866 if (!curproxy->fullconn)
7867 curproxy->fullconn = 1;
7868 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007869 }
7870
Willy Tarreau056f5682010-06-06 15:51:11 +02007871 /* initialize stick-tables on backend capable proxies. This must not
7872 * be done earlier because the data size may be discovered while parsing
7873 * other proxies.
7874 */
Godbach9703e662013-12-11 21:11:41 +08007875 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007876 if (curproxy->state == PR_STSTOPPED)
7877 continue;
7878
Godbach9703e662013-12-11 21:11:41 +08007879 if (!stktable_init(&curproxy->table)) {
7880 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7881 cfgerr++;
7882 }
7883 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007884
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007885 /*
7886 * Recount currently required checks.
7887 */
7888
7889 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7890 int optnum;
7891
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007892 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7893 if (curproxy->options & cfg_opts[optnum].val)
7894 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007895
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007896 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7897 if (curproxy->options2 & cfg_opts2[optnum].val)
7898 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007899 }
7900
Willy Tarreau122541c2011-09-07 21:24:49 +02007901 if (peers) {
7902 struct peers *curpeers = peers, **last;
7903 struct peer *p, *pb;
7904
7905 /* Remove all peers sections which don't have a valid listener.
7906 * This can happen when a peers section is never referenced and
7907 * does not contain a local peer.
7908 */
7909 last = &peers;
7910 while (*last) {
7911 curpeers = *last;
7912 if (curpeers->peers_fe) {
7913 last = &curpeers->next;
7914 continue;
7915 }
7916
7917 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7918 curpeers->id, localpeer);
7919
7920 p = curpeers->remote;
7921 while (p) {
7922 pb = p->next;
7923 free(p->id);
7924 free(p);
7925 p = pb;
7926 }
7927
7928 /* Destroy and unlink this curpeers section.
7929 * Note: curpeers is backed up into *last.
7930 */
7931 free(curpeers->id);
7932 curpeers = curpeers->next;
7933 free(*last);
7934 *last = curpeers;
7935 }
7936 }
7937
Simon Horman0d16a402015-01-30 11:22:58 +09007938 if (mailers) {
7939 struct mailers *curmailers = mailers, **last;
7940 struct mailer *m, *mb;
7941
7942 /* Remove all mailers sections which don't have a valid listener.
7943 * This can happen when a mailers section is never referenced.
7944 */
7945 last = &mailers;
7946 while (*last) {
7947 curmailers = *last;
7948 if (curmailers->users) {
7949 last = &curmailers->next;
7950 continue;
7951 }
7952
7953 Warning("Removing incomplete section 'mailers %s'.\n",
7954 curmailers->id);
7955
7956 m = curmailers->mailer_list;
7957 while (m) {
7958 mb = m->next;
7959 free(m->id);
7960 free(m);
7961 m = mb;
7962 }
7963
7964 /* Destroy and unlink this curmailers section.
7965 * Note: curmailers is backed up into *last.
7966 */
7967 free(curmailers->id);
7968 curmailers = curmailers->next;
7969 free(*last);
7970 *last = curmailers;
7971 }
7972 }
7973
Willy Tarreau34eb6712011-10-24 18:15:04 +02007974 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007975 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007976 MEM_F_SHARED);
7977
Willy Tarreaubb925012009-07-23 13:36:36 +02007978 if (cfgerr > 0)
7979 err_code |= ERR_ALERT | ERR_FATAL;
7980 out:
7981 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007982}
7983
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007984/*
7985 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7986 * parsing sessions.
7987 */
7988void cfg_register_keywords(struct cfg_kw_list *kwl)
7989{
7990 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7991}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007992
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007993/*
7994 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7995 */
7996void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7997{
7998 LIST_DEL(&kwl->list);
7999 LIST_INIT(&kwl->list);
8000}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008001
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008002/* this function register new section in the haproxy configuration file.
8003 * <section_name> is the name of this new section and <section_parser>
8004 * is the called parser. If two section declaration have the same name,
8005 * only the first declared is used.
8006 */
8007int cfg_register_section(char *section_name,
8008 int (*section_parser)(const char *, int, char **, int))
8009{
8010 struct cfg_section *cs;
8011
8012 cs = calloc(1, sizeof(*cs));
8013 if (!cs) {
8014 Alert("register section '%s': out of memory.\n", section_name);
8015 return 0;
8016 }
8017
8018 cs->section_name = section_name;
8019 cs->section_parser = section_parser;
8020
8021 LIST_ADDQ(&sections, &cs->list);
8022
8023 return 1;
8024}
8025
Willy Tarreaubaaee002006-06-26 02:48:02 +02008026/*
8027 * Local variables:
8028 * c-indent-level: 8
8029 * c-basic-offset: 8
8030 * End:
8031 */