blob: 09a0fd3d777671be64e0cbadd88d29b980c013d3 [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>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044
45#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010048#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020049#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050
Willy Tarreaueb0c6142007-05-07 00:53:22 +020051#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010052#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020054#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020056#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020057#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020058#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020059#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020060#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010061#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020062#include <proto/lb_fwlc.h>
63#include <proto/lb_fwrr.h>
64#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020065#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020066#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020067#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010068#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020069#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010070#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010071#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020072#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020073#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020074#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010075#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020076#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020077#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010078#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020079
Emeric Brunfc0421f2012-09-07 17:30:07 +020080#ifdef USE_OPENSSL
81#include <types/ssl_sock.h>
82#include <proto/ssl_sock.h>
83#include <proto/shctx.h>
84#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020085
Willy Tarreauf3c69202006-07-09 16:42:34 +020086/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
87 * ssl-hello-chk option to ensure that the remote server speaks SSL.
88 *
89 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
90 */
91const char sslv3_client_hello_pkt[] = {
92 "\x16" /* ContentType : 0x16 = Hanshake */
93 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
94 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
95 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
96 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
97 "\x03\x00" /* Hello Version : 0x0300 = v3 */
98 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
99 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
100 "\x00" /* Session ID length : empty (no session ID) */
101 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
102 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
103 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
104 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
105 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
106 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
107 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
108 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
109 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
110 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
111 "\x00\x38" "\x00\x39" "\x00\x3A"
112 "\x01" /* Compression Length : 0x01 = 1 byte for types */
113 "\x00" /* Compression Type : 0x00 = NULL compression */
114};
115
Willy Tarreau3842f002009-06-14 11:39:52 +0200116/* various keyword modifiers */
117enum kw_mod {
118 KWM_STD = 0, /* normal */
119 KWM_NO, /* "no" prefixed before the keyword */
120 KWM_DEF, /* "default" prefixed before the keyword */
121};
122
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100123/* permit to store configuration section */
124struct cfg_section {
125 struct list list;
126 char *section_name;
127 int (*section_parser)(const char *, int, char **, int);
128};
129
130/* Used to chain configuration sections definitions. This list
131 * stores struct cfg_section
132 */
133struct list sections = LIST_HEAD_INIT(sections);
134
Willy Tarreau13943ab2006-12-31 00:24:10 +0100135/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100136struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100137 const char *name;
138 unsigned int val;
139 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100140 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100141 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142};
143
144/* proxy->options */
145static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
148 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
149 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
150 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
151 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
152 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100154 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
156 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
157 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
158 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
159 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100160#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100161 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100162#else
163 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100164#endif
165
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100166 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100167};
168
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100169/* proxy->options2 */
170static const struct cfg_opt cfg_opts2[] =
171{
172#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
174 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
175 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100176#else
177 { "splice-request", 0, 0, 0, 0 },
178 { "splice-response", 0, 0, 0, 0 },
179 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100180#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100181 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
182 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
183 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
184 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
185 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
186 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
187 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
188 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
189 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400190 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100191 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200192 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200193 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100194 { NULL, 0, 0, 0 }
195};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196
Willy Tarreau6daf3432008-01-22 16:44:08 +0100197static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
199int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100200int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200202/* List head of all known configuration keywords */
203static struct cfg_kw_list cfg_keywords = {
204 .list = LIST_HEAD_INIT(cfg_keywords.list)
205};
206
Willy Tarreaubaaee002006-06-26 02:48:02 +0200207/*
208 * converts <str> to a list of listeners which are dynamically allocated.
209 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
210 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
211 * - <port> is a numerical port from 1 to 65535 ;
212 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
213 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200214 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
215 * not NULL, it must be a valid pointer to either NULL or a freeable area that
216 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200218int 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 +0200219{
220 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100221 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 int port, end;
223
224 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200225
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100227 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100228 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229
230 str = next;
231 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100232 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 *next++ = 0;
234 }
235
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100236 ss2 = str2sa_range(str, &port, &end, err,
237 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
238 if (!ss2)
239 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100241 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100242 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200243 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100244 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100247 if (!port || !end) {
248 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
249 goto fail;
250 }
251
Emeric Bruned760922010-10-22 17:59:25 +0200252 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200253 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200254 goto fail;
255 }
256
257 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200258 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200259 goto fail;
260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200261 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100262 else if (ss2->ss_family == AF_UNSPEC) {
263 socklen_t addr_len;
264
265 /* We want to attach to an already bound fd whose number
266 * is in the addr part of ss2 when cast to sockaddr_in.
267 * Note that by definition there is a single listener.
268 * We still have to determine the address family to
269 * register the correct protocol.
270 */
271 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
272 addr_len = sizeof(*ss2);
273 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
274 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
275 goto fail;
276 }
277
278 port = end = get_host_port(ss2);
279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200280
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100281 /* OK the address looks correct */
282 ss = *ss2;
283
Willy Tarreaubaaee002006-06-26 02:48:02 +0200284 for (; port <= end; port++) {
285 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100286 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200287 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
288 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
289 l->frontend = curproxy;
290 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200291
Willy Tarreau40aa0702013-03-10 23:51:38 +0100292 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200294 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100295 l->state = LI_INIT;
296
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100297 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100299 tcpv4_add_listener(l);
300 }
Emeric Bruned760922010-10-22 17:59:25 +0200301 else if (ss.ss_family == AF_INET6) {
302 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
303 tcpv6_add_listener(l);
304 }
305 else {
Emeric Bruned760922010-10-22 17:59:25 +0200306 uxst_add_listener(l);
307 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200308
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200309 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100310 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200311 } /* end for(port) */
312 } /* end while(next) */
313 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200314 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315 fail:
316 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200317 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318}
319
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200320/* Report a warning if a rule is placed after a 'tcp-request content' rule.
321 * Return 1 if the warning has been emitted, otherwise 0.
322 */
323int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
324{
325 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
326 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
327 file, line, arg);
328 return 1;
329 }
330 return 0;
331}
332
Willy Tarreau61d18892009-03-31 10:49:21 +0200333/* Report a warning if a rule is placed after a 'block' rule.
334 * Return 1 if the warning has been emitted, otherwise 0.
335 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100336int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200337{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200338 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200339 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
340 file, line, arg);
341 return 1;
342 }
343 return 0;
344}
345
Willy Tarreau5002f572014-04-23 01:32:02 +0200346/* Report a warning if a rule is placed after an 'http_request' rule.
347 * Return 1 if the warning has been emitted, otherwise 0.
348 */
349int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
350{
351 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
352 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
353 file, line, arg);
354 return 1;
355 }
356 return 0;
357}
358
Willy Tarreau61d18892009-03-31 10:49:21 +0200359/* Report a warning if a rule is placed after a reqrewrite rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100362int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200363{
364 if (proxy->req_exp) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
366 file, line, arg);
367 return 1;
368 }
369 return 0;
370}
371
372/* Report a warning if a rule is placed after a reqadd rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100377 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
379 file, line, arg);
380 return 1;
381 }
382 return 0;
383}
384
385/* Report a warning if a rule is placed after a redirect rule.
386 * Return 1 if the warning has been emitted, otherwise 0.
387 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100388int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200389{
390 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
391 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
392 file, line, arg);
393 return 1;
394 }
395 return 0;
396}
397
398/* Report a warning if a rule is placed after a 'use_backend' rule.
399 * Return 1 if the warning has been emitted, otherwise 0.
400 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
404 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
405 file, line, arg);
406 return 1;
407 }
408 return 0;
409}
410
Willy Tarreauee445d92014-04-23 01:39:04 +0200411/* Report a warning if a rule is placed after a 'use-server' rule.
412 * Return 1 if the warning has been emitted, otherwise 0.
413 */
414int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
415{
416 if (!LIST_ISEMPTY(&proxy->server_rules)) {
417 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
418 file, line, arg);
419 return 1;
420 }
421 return 0;
422}
423
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200424/* report a warning if a "tcp request connection" rule is dangerously placed */
425int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
426{
427 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
428 warnif_rule_after_block(proxy, file, line, arg) ||
429 warnif_rule_after_http_req(proxy, file, line, arg) ||
430 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
431 warnif_rule_after_reqadd(proxy, file, line, arg) ||
432 warnif_rule_after_redirect(proxy, file, line, arg) ||
433 warnif_rule_after_use_backend(proxy, file, line, arg) ||
434 warnif_rule_after_use_server(proxy, file, line, arg);
435}
436
437/* report a warning if a "tcp request content" rule is dangerously placed */
438int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
439{
440 return warnif_rule_after_block(proxy, file, line, arg) ||
441 warnif_rule_after_http_req(proxy, file, line, arg) ||
442 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
443 warnif_rule_after_reqadd(proxy, file, line, arg) ||
444 warnif_rule_after_redirect(proxy, file, line, arg) ||
445 warnif_rule_after_use_backend(proxy, file, line, arg) ||
446 warnif_rule_after_use_server(proxy, file, line, arg);
447}
448
Willy Tarreau61d18892009-03-31 10:49:21 +0200449/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100450int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200451{
Willy Tarreau5002f572014-04-23 01:32:02 +0200452 return warnif_rule_after_http_req(proxy, file, line, arg) ||
453 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
454 warnif_rule_after_reqadd(proxy, file, line, arg) ||
455 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200456 warnif_rule_after_use_backend(proxy, file, line, arg) ||
457 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200458}
459
460/* report a warning if an http-request rule is dangerously placed */
461int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
462{
Willy Tarreau61d18892009-03-31 10:49:21 +0200463 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
464 warnif_rule_after_reqadd(proxy, file, line, arg) ||
465 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200466 warnif_rule_after_use_backend(proxy, file, line, arg) ||
467 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200468}
469
470/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100471int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200472{
473 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
474 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200475 warnif_rule_after_use_backend(proxy, file, line, arg) ||
476 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200477}
478
479/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100480int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200481{
482 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200483 warnif_rule_after_use_backend(proxy, file, line, arg) ||
484 warnif_rule_after_use_server(proxy, file, line, arg);
485}
486
487/* report a warning if a redirect rule is dangerously placed */
488int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
489{
490 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
491 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200492}
493
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100494/* Report it if a request ACL condition uses some keywords that are incompatible
495 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
496 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
497 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100498 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100499static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100500{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100501 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200502 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100503
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100504 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100505 return 0;
506
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100507 acl = acl_cond_conflicts(cond, where);
508 if (acl) {
509 if (acl->name && *acl->name)
510 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
511 file, line, acl->name, sample_ckp_names(where));
512 else
513 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 +0200514 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100515 return ERR_WARN;
516 }
517 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100518 return 0;
519
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100520 if (acl->name && *acl->name)
521 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200522 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100523 else
524 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200525 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100526 return ERR_WARN;
527}
528
Willy Tarreaubaaee002006-06-26 02:48:02 +0200529/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200530 * parse a line in a <global> section. Returns the error code, 0 if OK, or
531 * any combination of :
532 * - ERR_ABORT: must abort ASAP
533 * - ERR_FATAL: we can continue parsing but not start the service
534 * - ERR_WARN: a warning has been emitted
535 * - ERR_ALERT: an alert has been emitted
536 * Only the two first ones can stop processing, the two others are just
537 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200538 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200539int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200540{
Willy Tarreau058e9072009-07-20 09:30:05 +0200541 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200542 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200543
544 if (!strcmp(args[0], "global")) { /* new section */
545 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200547 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200548 else if (!strcmp(args[0], "ca-base")) {
549#ifdef USE_OPENSSL
550 if (global.ca_base != NULL) {
551 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
552 err_code |= ERR_ALERT;
553 goto out;
554 }
555 if (*(args[1]) == 0) {
556 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
557 err_code |= ERR_ALERT | ERR_FATAL;
558 goto out;
559 }
560 global.ca_base = strdup(args[1]);
561#else
562 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
563 err_code |= ERR_ALERT | ERR_FATAL;
564 goto out;
565#endif
566 }
567 else if (!strcmp(args[0], "crt-base")) {
568#ifdef USE_OPENSSL
569 if (global.crt_base != NULL) {
570 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
571 err_code |= ERR_ALERT;
572 goto out;
573 }
574 if (*(args[1]) == 0) {
575 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
576 err_code |= ERR_ALERT | ERR_FATAL;
577 goto out;
578 }
579 global.crt_base = strdup(args[1]);
580#else
581 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
582 err_code |= ERR_ALERT | ERR_FATAL;
583 goto out;
584#endif
585 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200586 else if (!strcmp(args[0], "daemon")) {
587 global.mode |= MODE_DAEMON;
588 }
589 else if (!strcmp(args[0], "debug")) {
590 global.mode |= MODE_DEBUG;
591 }
592 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100593 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200594 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200595 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100596 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200597 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200598 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100599 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200600 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100601 else if (!strcmp(args[0], "nosplice")) {
602 global.tune.options &= ~GTUNE_USE_SPLICE;
603 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200604 else if (!strcmp(args[0], "nogetaddrinfo")) {
605 global.tune.options &= ~GTUNE_USE_GAI;
606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607 else if (!strcmp(args[0], "quiet")) {
608 global.mode |= MODE_QUIET;
609 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200610 else if (!strcmp(args[0], "tune.maxpollevents")) {
611 if (global.tune.maxpollevents != 0) {
612 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200613 err_code |= ERR_ALERT;
614 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200615 }
616 if (*(args[1]) == 0) {
617 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200618 err_code |= ERR_ALERT | ERR_FATAL;
619 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200620 }
621 global.tune.maxpollevents = atol(args[1]);
622 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100623 else if (!strcmp(args[0], "tune.maxaccept")) {
624 if (global.tune.maxaccept != 0) {
625 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200626 err_code |= ERR_ALERT;
627 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100628 }
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100633 }
634 global.tune.maxaccept = atol(args[1]);
635 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200636 else if (!strcmp(args[0], "tune.chksize")) {
637 if (*(args[1]) == 0) {
638 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
641 }
642 global.tune.chksize = atol(args[1]);
643 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200644#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200645 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
646 global.tune.sslprivatecache = 1;
647 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100648 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200649 if (*(args[1]) == 0) {
650 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
651 err_code |= ERR_ALERT | ERR_FATAL;
652 goto out;
653 }
654 global.tune.sslcachesize = atol(args[1]);
655 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100656 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
657 unsigned int ssllifetime;
658 const char *res;
659
660 if (*(args[1]) == 0) {
661 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
662 err_code |= ERR_ALERT | ERR_FATAL;
663 goto out;
664 }
665
666 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
667 if (res) {
668 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
669 file, linenum, *res, args[0]);
670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
672 }
673
674 global.tune.ssllifetime = ssllifetime;
675 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100676 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
677 if (*(args[1]) == 0) {
678 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
681 }
682 global.tune.ssl_max_record = atol(args[1]);
683 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200684 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
685 if (*(args[1]) == 0) {
686 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
687 err_code |= ERR_ALERT | ERR_FATAL;
688 goto out;
689 }
690 global.tune.ssl_default_dh_param = atol(args[1]);
691 if (global.tune.ssl_default_dh_param < 1024) {
692 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
695 }
696 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200697#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200698 else if (!strcmp(args[0], "tune.bufsize")) {
699 if (*(args[1]) == 0) {
700 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
703 }
704 global.tune.bufsize = atol(args[1]);
705 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
706 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100707 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100708 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200709 }
710 else if (!strcmp(args[0], "tune.maxrewrite")) {
711 if (*(args[1]) == 0) {
712 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
713 err_code |= ERR_ALERT | ERR_FATAL;
714 goto out;
715 }
716 global.tune.maxrewrite = atol(args[1]);
717 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
718 global.tune.maxrewrite = global.tune.bufsize / 2;
719 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100720 else if (!strcmp(args[0], "tune.idletimer")) {
721 unsigned int idle;
722 const char *res;
723
724 if (*(args[1]) == 0) {
725 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
726 err_code |= ERR_ALERT | ERR_FATAL;
727 goto out;
728 }
729
730 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
731 if (res) {
732 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
733 file, linenum, *res, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737
738 if (idle > 65535) {
739 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743 global.tune.idle_timer = idle;
744 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100745 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
746 if (global.tune.client_rcvbuf != 0) {
747 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
748 err_code |= ERR_ALERT;
749 goto out;
750 }
751 if (*(args[1]) == 0) {
752 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756 global.tune.client_rcvbuf = atol(args[1]);
757 }
758 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
759 if (global.tune.server_rcvbuf != 0) {
760 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
761 err_code |= ERR_ALERT;
762 goto out;
763 }
764 if (*(args[1]) == 0) {
765 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
766 err_code |= ERR_ALERT | ERR_FATAL;
767 goto out;
768 }
769 global.tune.server_rcvbuf = atol(args[1]);
770 }
771 else if (!strcmp(args[0], "tune.sndbuf.client")) {
772 if (global.tune.client_sndbuf != 0) {
773 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
774 err_code |= ERR_ALERT;
775 goto out;
776 }
777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
781 }
782 global.tune.client_sndbuf = atol(args[1]);
783 }
784 else if (!strcmp(args[0], "tune.sndbuf.server")) {
785 if (global.tune.server_sndbuf != 0) {
786 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
787 err_code |= ERR_ALERT;
788 goto out;
789 }
790 if (*(args[1]) == 0) {
791 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
794 }
795 global.tune.server_sndbuf = atol(args[1]);
796 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200797 else if (!strcmp(args[0], "tune.pipesize")) {
798 if (*(args[1]) == 0) {
799 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
800 err_code |= ERR_ALERT | ERR_FATAL;
801 goto out;
802 }
803 global.tune.pipesize = atol(args[1]);
804 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100805 else if (!strcmp(args[0], "tune.http.cookielen")) {
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.cookie_len = atol(args[1]) + 1;
812 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200813 else if (!strcmp(args[0], "tune.http.maxhdr")) {
814 if (*(args[1]) == 0) {
815 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
816 err_code |= ERR_ALERT | ERR_FATAL;
817 goto out;
818 }
819 global.tune.max_http_hdr = atol(args[1]);
820 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100821 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
822#ifdef USE_ZLIB
823 if (*args[1]) {
824 global.tune.zlibmemlevel = atoi(args[1]);
825 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
826 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
827 file, linenum, args[0]);
828 err_code |= ERR_ALERT | ERR_FATAL;
829 goto out;
830 }
831 } else {
832 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
833 file, linenum, args[0]);
834 err_code |= ERR_ALERT | ERR_FATAL;
835 goto out;
836 }
837#else
838 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
839 err_code |= ERR_ALERT | ERR_FATAL;
840 goto out;
841#endif
842 }
843 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
844#ifdef USE_ZLIB
845 if (*args[1]) {
846 global.tune.zlibwindowsize = atoi(args[1]);
847 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
848 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
849 file, linenum, args[0]);
850 err_code |= ERR_ALERT | ERR_FATAL;
851 goto out;
852 }
853 } else {
854 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
855 file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859#else
860 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863#endif
864 }
William Lallemandf3747832012-11-09 12:33:10 +0100865 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
866 if (*args[1]) {
867 global.tune.comp_maxlevel = atoi(args[1]);
868 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
869 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
870 file, linenum, args[0]);
871 err_code |= ERR_ALERT | ERR_FATAL;
872 goto out;
873 }
874 } else {
875 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
876 file, linenum, args[0]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200881 else if (!strcmp(args[0], "uid")) {
882 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200883 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200884 err_code |= ERR_ALERT;
885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200886 }
887 if (*(args[1]) == 0) {
888 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200889 err_code |= ERR_ALERT | ERR_FATAL;
890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200891 }
892 global.uid = atol(args[1]);
893 }
894 else if (!strcmp(args[0], "gid")) {
895 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200896 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200897 err_code |= ERR_ALERT;
898 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200899 }
900 if (*(args[1]) == 0) {
901 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200902 err_code |= ERR_ALERT | ERR_FATAL;
903 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904 }
905 global.gid = atol(args[1]);
906 }
Simon Horman98637e52014-06-20 12:30:16 +0900907 else if (!strcmp(args[0], "external-check")) {
908 global.external_check = 1;
909 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200910 /* user/group name handling */
911 else if (!strcmp(args[0], "user")) {
912 struct passwd *ha_user;
913 if (global.uid != 0) {
914 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200915 err_code |= ERR_ALERT;
916 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200917 }
918 errno = 0;
919 ha_user = getpwnam(args[1]);
920 if (ha_user != NULL) {
921 global.uid = (int)ha_user->pw_uid;
922 }
923 else {
924 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 +0200925 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200926 }
927 }
928 else if (!strcmp(args[0], "group")) {
929 struct group *ha_group;
930 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200931 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200932 err_code |= ERR_ALERT;
933 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200934 }
935 errno = 0;
936 ha_group = getgrnam(args[1]);
937 if (ha_group != NULL) {
938 global.gid = (int)ha_group->gr_gid;
939 }
940 else {
941 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 +0200942 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200943 }
944 }
945 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200946 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947 if (*(args[1]) == 0) {
948 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200949 err_code |= ERR_ALERT | ERR_FATAL;
950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 }
952 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100953 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
954 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
955 file, linenum, args[0], LONGBITS, global.nbproc);
956 err_code |= ERR_ALERT | ERR_FATAL;
957 goto out;
958 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200959 }
960 else if (!strcmp(args[0], "maxconn")) {
961 if (global.maxconn != 0) {
962 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200963 err_code |= ERR_ALERT;
964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200965 }
966 if (*(args[1]) == 0) {
967 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200968 err_code |= ERR_ALERT | ERR_FATAL;
969 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970 }
971 global.maxconn = atol(args[1]);
972#ifdef SYSTEM_MAXCONN
973 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
974 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);
975 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200976 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200977 }
978#endif /* SYSTEM_MAXCONN */
979 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200980 else if (!strcmp(args[0], "maxsslconn")) {
981#ifdef USE_OPENSSL
982 if (*(args[1]) == 0) {
983 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
984 err_code |= ERR_ALERT | ERR_FATAL;
985 goto out;
986 }
987 global.maxsslconn = atol(args[1]);
988#else
Emeric Brun0914df82012-10-02 18:45:42 +0200989 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
990 err_code |= ERR_ALERT | ERR_FATAL;
991 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200992#endif
993 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100994 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
995#ifdef USE_OPENSSL
996 if (*(args[1]) == 0) {
997 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
998 err_code |= ERR_ALERT | ERR_FATAL;
999 goto out;
1000 }
1001 free(global.listen_default_ciphers);
1002 global.listen_default_ciphers = strdup(args[1]);
1003#else
1004 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1005 err_code |= ERR_ALERT | ERR_FATAL;
1006 goto out;
1007#endif
1008 }
1009 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1010#ifdef USE_OPENSSL
1011 if (*(args[1]) == 0) {
1012 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1013 err_code |= ERR_ALERT | ERR_FATAL;
1014 goto out;
1015 }
1016 free(global.connect_default_ciphers);
1017 global.connect_default_ciphers = strdup(args[1]);
1018#else
1019 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1020 err_code |= ERR_ALERT | ERR_FATAL;
1021 goto out;
1022#endif
1023 }
Emeric Brun850efd52014-01-29 12:24:34 +01001024 else if (!strcmp(args[0], "ssl-server-verify")) {
1025 if (*(args[1]) == 0) {
1026 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1027 err_code |= ERR_ALERT | ERR_FATAL;
1028 goto out;
1029 }
1030 if (strcmp(args[1],"none") == 0)
1031 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1032 else if (strcmp(args[1],"required") == 0)
1033 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1034 else {
1035 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1036 err_code |= ERR_ALERT | ERR_FATAL;
1037 goto out;
1038 }
1039 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001040 else if (!strcmp(args[0], "maxconnrate")) {
1041 if (global.cps_lim != 0) {
1042 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1043 err_code |= ERR_ALERT;
1044 goto out;
1045 }
1046 if (*(args[1]) == 0) {
1047 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1048 err_code |= ERR_ALERT | ERR_FATAL;
1049 goto out;
1050 }
1051 global.cps_lim = atol(args[1]);
1052 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001053 else if (!strcmp(args[0], "maxsessrate")) {
1054 if (global.sps_lim != 0) {
1055 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1056 err_code |= ERR_ALERT;
1057 goto out;
1058 }
1059 if (*(args[1]) == 0) {
1060 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1061 err_code |= ERR_ALERT | ERR_FATAL;
1062 goto out;
1063 }
1064 global.sps_lim = atol(args[1]);
1065 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001066 else if (!strcmp(args[0], "maxsslrate")) {
1067 if (global.ssl_lim != 0) {
1068 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1069 err_code |= ERR_ALERT;
1070 goto out;
1071 }
1072 if (*(args[1]) == 0) {
1073 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1074 err_code |= ERR_ALERT | ERR_FATAL;
1075 goto out;
1076 }
1077 global.ssl_lim = atol(args[1]);
1078 }
William Lallemandd85f9172012-11-09 17:05:39 +01001079 else if (!strcmp(args[0], "maxcomprate")) {
1080 if (*(args[1]) == 0) {
1081 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1082 err_code |= ERR_ALERT | ERR_FATAL;
1083 goto out;
1084 }
1085 global.comp_rate_lim = atoi(args[1]) * 1024;
1086 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001087 else if (!strcmp(args[0], "maxpipes")) {
1088 if (global.maxpipes != 0) {
1089 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT;
1091 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001092 }
1093 if (*(args[1]) == 0) {
1094 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001097 }
1098 global.maxpipes = atol(args[1]);
1099 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001100 else if (!strcmp(args[0], "maxzlibmem")) {
1101 if (*(args[1]) == 0) {
1102 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1103 err_code |= ERR_ALERT | ERR_FATAL;
1104 goto out;
1105 }
William Lallemande3a7d992012-11-20 11:25:20 +01001106 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001107 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001108 else if (!strcmp(args[0], "maxcompcpuusage")) {
1109 if (*(args[1]) == 0) {
1110 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1111 err_code |= ERR_ALERT | ERR_FATAL;
1112 goto out;
1113 }
1114 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001115 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001116 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1117 err_code |= ERR_ALERT | ERR_FATAL;
1118 goto out;
1119 }
1120}
1121
Willy Tarreaubaaee002006-06-26 02:48:02 +02001122 else if (!strcmp(args[0], "ulimit-n")) {
1123 if (global.rlimit_nofile != 0) {
1124 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001125 err_code |= ERR_ALERT;
1126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001127 }
1128 if (*(args[1]) == 0) {
1129 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001130 err_code |= ERR_ALERT | ERR_FATAL;
1131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001132 }
1133 global.rlimit_nofile = atol(args[1]);
1134 }
1135 else if (!strcmp(args[0], "chroot")) {
1136 if (global.chroot != NULL) {
1137 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001138 err_code |= ERR_ALERT;
1139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001140 }
1141 if (*(args[1]) == 0) {
1142 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001143 err_code |= ERR_ALERT | ERR_FATAL;
1144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001145 }
1146 global.chroot = strdup(args[1]);
1147 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001148 else if (!strcmp(args[0], "description")) {
1149 int i, len=0;
1150 char *d;
1151
1152 if (!*args[1]) {
1153 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1154 file, linenum, args[0]);
1155 err_code |= ERR_ALERT | ERR_FATAL;
1156 goto out;
1157 }
1158
Willy Tarreau348acfe2014-04-14 15:00:39 +02001159 for (i = 1; *args[i]; i++)
1160 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001161
1162 if (global.desc)
1163 free(global.desc);
1164
1165 global.desc = d = (char *)calloc(1, len);
1166
Willy Tarreau348acfe2014-04-14 15:00:39 +02001167 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1168 for (i = 2; *args[i]; i++)
1169 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001170 }
1171 else if (!strcmp(args[0], "node")) {
1172 int i;
1173 char c;
1174
1175 for (i=0; args[1][i]; i++) {
1176 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001177 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1178 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001179 break;
1180 }
1181
1182 if (!i || args[1][i]) {
1183 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1184 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1185 file, linenum, args[0]);
1186 err_code |= ERR_ALERT | ERR_FATAL;
1187 goto out;
1188 }
1189
1190 if (global.node)
1191 free(global.node);
1192
1193 global.node = strdup(args[1]);
1194 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001195 else if (!strcmp(args[0], "pidfile")) {
1196 if (global.pidfile != NULL) {
1197 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001198 err_code |= ERR_ALERT;
1199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001200 }
1201 if (*(args[1]) == 0) {
1202 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001203 err_code |= ERR_ALERT | ERR_FATAL;
1204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 }
1206 global.pidfile = strdup(args[1]);
1207 }
Emeric Bruned760922010-10-22 17:59:25 +02001208 else if (!strcmp(args[0], "unix-bind")) {
1209 int cur_arg = 1;
1210 while (*(args[cur_arg])) {
1211 if (!strcmp(args[cur_arg], "prefix")) {
1212 if (global.unix_bind.prefix != NULL) {
1213 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1214 err_code |= ERR_ALERT;
1215 cur_arg += 2;
1216 continue;
1217 }
1218
1219 if (*(args[cur_arg+1]) == 0) {
1220 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1221 err_code |= ERR_ALERT | ERR_FATAL;
1222 goto out;
1223 }
1224 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1225 cur_arg += 2;
1226 continue;
1227 }
1228
1229 if (!strcmp(args[cur_arg], "mode")) {
1230
1231 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1232 cur_arg += 2;
1233 continue;
1234 }
1235
1236 if (!strcmp(args[cur_arg], "uid")) {
1237
1238 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1239 cur_arg += 2;
1240 continue;
1241 }
1242
1243 if (!strcmp(args[cur_arg], "gid")) {
1244
1245 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1246 cur_arg += 2;
1247 continue;
1248 }
1249
1250 if (!strcmp(args[cur_arg], "user")) {
1251 struct passwd *user;
1252
1253 user = getpwnam(args[cur_arg + 1]);
1254 if (!user) {
1255 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1256 file, linenum, args[0], args[cur_arg + 1 ]);
1257 err_code |= ERR_ALERT | ERR_FATAL;
1258 goto out;
1259 }
1260
1261 global.unix_bind.ux.uid = user->pw_uid;
1262 cur_arg += 2;
1263 continue;
1264 }
1265
1266 if (!strcmp(args[cur_arg], "group")) {
1267 struct group *group;
1268
1269 group = getgrnam(args[cur_arg + 1]);
1270 if (!group) {
1271 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1272 file, linenum, args[0], args[cur_arg + 1 ]);
1273 err_code |= ERR_ALERT | ERR_FATAL;
1274 goto out;
1275 }
1276
1277 global.unix_bind.ux.gid = group->gr_gid;
1278 cur_arg += 2;
1279 continue;
1280 }
1281
Willy Tarreaub48f9582011-09-05 01:17:06 +02001282 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001283 file, linenum, args[0]);
1284 err_code |= ERR_ALERT | ERR_FATAL;
1285 goto out;
1286 }
1287 }
William Lallemand0f99e342011-10-12 17:50:54 +02001288 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1289 /* delete previous herited or defined syslog servers */
1290 struct logsrv *back;
1291 struct logsrv *tmp;
1292
1293 if (*(args[1]) != 0) {
1294 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1295 err_code |= ERR_ALERT | ERR_FATAL;
1296 goto out;
1297 }
1298
1299 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1300 LIST_DEL(&tmp->list);
1301 free(tmp);
1302 }
1303 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001304 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001305 struct sockaddr_storage *sk;
1306 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001307 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001308 int arg = 0;
1309 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001310
Willy Tarreaubaaee002006-06-26 02:48:02 +02001311 if (*(args[1]) == 0 || *(args[2]) == 0) {
1312 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001313 err_code |= ERR_ALERT | ERR_FATAL;
1314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001315 }
William Lallemand0f99e342011-10-12 17:50:54 +02001316
1317 logsrv = calloc(1, sizeof(struct logsrv));
1318
Willy Tarreau18324f52014-06-27 18:10:07 +02001319 /* just after the address, a length may be specified */
1320 if (strcmp(args[arg+2], "len") == 0) {
1321 len = atoi(args[arg+3]);
1322 if (len < 80 || len > 65535) {
1323 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1324 file, linenum, args[arg+3]);
1325 err_code |= ERR_ALERT | ERR_FATAL;
1326 goto out;
1327 }
1328 logsrv->maxlen = len;
1329
1330 /* skip these two args */
1331 arg += 2;
1332 }
1333 else
1334 logsrv->maxlen = MAX_SYSLOG_LEN;
1335
1336 if (logsrv->maxlen > global.max_syslog_len) {
1337 global.max_syslog_len = logsrv->maxlen;
1338 logline = realloc(logline, global.max_syslog_len + 1);
1339 }
1340
1341 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001342 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001343 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001344 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001345 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001346 }
1347
William Lallemand0f99e342011-10-12 17:50:54 +02001348 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001349 if (*(args[arg+3])) {
1350 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001351 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001352 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001353 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001354 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001355 }
1356 }
1357
William Lallemand0f99e342011-10-12 17:50:54 +02001358 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001359 if (*(args[arg+4])) {
1360 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001361 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001362 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001363 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001364 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001365 }
1366 }
1367
Willy Tarreau902636f2013-03-10 19:44:48 +01001368 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001369 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001370 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001371 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001372 free(logsrv);
1373 goto out;
1374 }
1375 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001376
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001377 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001378 if (port1 != port2) {
1379 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1380 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001381 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001382 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001383 goto out;
1384 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001385
William Lallemand0f99e342011-10-12 17:50:54 +02001386 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001387 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001388 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001389 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390
William Lallemand0f99e342011-10-12 17:50:54 +02001391 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001392 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001393 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1394 char *name;
1395 int len;
1396
1397 if (global.log_send_hostname != NULL) {
1398 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1399 err_code |= ERR_ALERT;
1400 goto out;
1401 }
1402
1403 if (*(args[1]))
1404 name = args[1];
1405 else
1406 name = hostname;
1407
1408 len = strlen(name);
1409
1410 /* We'll add a space after the name to respect the log format */
1411 free(global.log_send_hostname);
1412 global.log_send_hostname = malloc(len + 2);
1413 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1414 }
Kevinm48936af2010-12-22 16:08:21 +00001415 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1416 if (*(args[1]) == 0) {
1417 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1418 err_code |= ERR_ALERT | ERR_FATAL;
1419 goto out;
1420 }
1421 free(global.log_tag);
1422 global.log_tag = strdup(args[1]);
1423 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001424 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1425 if (global.spread_checks != 0) {
1426 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001427 err_code |= ERR_ALERT;
1428 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001429 }
1430 if (*(args[1]) == 0) {
1431 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001432 err_code |= ERR_ALERT | ERR_FATAL;
1433 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001434 }
1435 global.spread_checks = atol(args[1]);
1436 if (global.spread_checks < 0 || global.spread_checks > 50) {
1437 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001438 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001439 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001440 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001441 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1442 const char *err;
1443 unsigned int val;
1444
1445
1446 if (*(args[1]) == 0) {
1447 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1448 err_code |= ERR_ALERT | ERR_FATAL;
1449 goto out;
1450 }
1451
1452 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1453 if (err) {
1454 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1455 err_code |= ERR_ALERT | ERR_FATAL;
1456 }
1457 global.max_spread_checks = val;
1458 if (global.max_spread_checks < 0) {
1459 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1460 err_code |= ERR_ALERT | ERR_FATAL;
1461 }
1462 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001463 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1464#ifdef USE_CPU_AFFINITY
1465 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001466 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001467 unsigned long cpus = 0;
1468
1469 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001470 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001471 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001472 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001473 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001474 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001475 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001476 proc = atol(args[1]);
1477 if (proc >= 1 && proc <= LONGBITS)
1478 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001479 }
1480
1481 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001482 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",
1483 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001484 err_code |= ERR_ALERT | ERR_FATAL;
1485 goto out;
1486 }
1487
1488 cur_arg = 2;
1489 while (*args[cur_arg]) {
1490 unsigned int low, high;
1491
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001492 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001493 char *dash = strchr(args[cur_arg], '-');
1494
1495 low = high = str2uic(args[cur_arg]);
1496 if (dash)
1497 high = str2uic(dash + 1);
1498
1499 if (high < low) {
1500 unsigned int swap = low;
1501 low = high;
1502 high = swap;
1503 }
1504
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001505 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001506 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001507 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001508 err_code |= ERR_ALERT | ERR_FATAL;
1509 goto out;
1510 }
1511
1512 while (low <= high)
1513 cpus |= 1UL << low++;
1514 }
1515 else {
1516 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1517 file, linenum, args[0], args[cur_arg]);
1518 err_code |= ERR_ALERT | ERR_FATAL;
1519 goto out;
1520 }
1521 cur_arg++;
1522 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001523 for (i = 0; i < LONGBITS; i++)
1524 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001525 global.cpu_map[i] = cpus;
1526#else
1527 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1528 err_code |= ERR_ALERT | ERR_FATAL;
1529 goto out;
1530#endif
1531 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001532 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001533 struct cfg_kw_list *kwl;
1534 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001535 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001536
1537 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1538 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1539 if (kwl->kw[index].section != CFG_GLOBAL)
1540 continue;
1541 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001542 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001543 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001544 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001545 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001546 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001547 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001548 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001549 err_code |= ERR_WARN;
1550 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001551 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001552 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001553 }
1554 }
1555 }
1556
Willy Tarreaubaaee002006-06-26 02:48:02 +02001557 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001558 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001560
Willy Tarreau058e9072009-07-20 09:30:05 +02001561 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001562 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001563 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001564}
1565
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001566void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001567{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001568 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001569 defproxy.mode = PR_MODE_TCP;
1570 defproxy.state = PR_STNEW;
1571 defproxy.maxconn = cfg_maxpconn;
1572 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001573
Simon Horman66183002013-02-23 10:16:43 +09001574 defproxy.defsrv.check.inter = DEF_CHKINTR;
1575 defproxy.defsrv.check.fastinter = 0;
1576 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001577 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1578 defproxy.defsrv.agent.fastinter = 0;
1579 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001580 defproxy.defsrv.check.rise = DEF_RISETIME;
1581 defproxy.defsrv.check.fall = DEF_FALLTIME;
1582 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1583 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001584 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001585 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001586 defproxy.defsrv.maxqueue = 0;
1587 defproxy.defsrv.minconn = 0;
1588 defproxy.defsrv.maxconn = 0;
1589 defproxy.defsrv.slowstart = 0;
1590 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1591 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1592 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001593}
1594
Willy Tarreauade5ec42010-01-28 19:33:49 +01001595
Willy Tarreau63af98d2014-05-18 08:11:41 +02001596/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1597 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1598 * ERR_FATAL in case of error.
1599 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001600static int create_cond_regex_rule(const char *file, int line,
1601 struct proxy *px, int dir, int action, int flags,
1602 const char *cmd, const char *reg, const char *repl,
1603 const char **cond_start)
1604{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001605 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001606 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001607 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001608 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001609 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001610 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001611 int cs;
1612 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001613
1614 if (px == &defproxy) {
1615 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001616 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001617 goto err;
1618 }
1619
1620 if (*reg == 0) {
1621 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001622 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001623 goto err;
1624 }
1625
1626 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001627 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001628
Willy Tarreau5321c422010-01-28 20:35:13 +01001629 if (cond_start &&
1630 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001631 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1632 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1633 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001634 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001635 goto err;
1636 }
1637 }
1638 else if (cond_start && **cond_start) {
1639 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1640 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001641 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001642 goto err;
1643 }
1644
Willy Tarreau63af98d2014-05-18 08:11:41 +02001645 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001646 (dir == SMP_OPT_DIR_REQ) ?
1647 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1648 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1649 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001650
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001651 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001652 if (!preg) {
1653 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001654 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001655 goto err;
1656 }
1657
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001658 cs = !(flags & REG_ICASE);
1659 cap = !(flags & REG_NOSUB);
1660 error = NULL;
1661 if (!regex_comp(reg, preg, cs, cap, &error)) {
1662 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1663 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001664 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001665 goto err;
1666 }
1667
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001668 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001669 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001670 if (repl && err) {
1671 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1672 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001673 ret_code |= ERR_ALERT | ERR_FATAL;
1674 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001675 }
1676
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001677 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001678 ret_code |= ERR_WARN;
1679
1680 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001681
Willy Tarreau63af98d2014-05-18 08:11:41 +02001682 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001683 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001684 err:
1685 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001686 free(errmsg);
1687 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001688}
1689
Willy Tarreaubaaee002006-06-26 02:48:02 +02001690/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001691 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001692 * Returns the error code, 0 if OK, or any combination of :
1693 * - ERR_ABORT: must abort ASAP
1694 * - ERR_FATAL: we can continue parsing but not start the service
1695 * - ERR_WARN: a warning has been emitted
1696 * - ERR_ALERT: an alert has been emitted
1697 * Only the two first ones can stop processing, the two others are just
1698 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001699 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001700int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1701{
1702 static struct peers *curpeers = NULL;
1703 struct peer *newpeer = NULL;
1704 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001705 struct bind_conf *bind_conf;
1706 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001707 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001708 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001709
1710 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001711 if (!*args[1]) {
1712 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001713 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001714 goto out;
1715 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001716
1717 err = invalid_char(args[1]);
1718 if (err) {
1719 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1720 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001721 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001722 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001723 }
1724
1725 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1726 /*
1727 * If there are two proxies with the same name only following
1728 * combinations are allowed:
1729 */
1730 if (strcmp(curpeers->id, args[1]) == 0) {
1731 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1732 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1733 err_code |= ERR_WARN;
1734 }
1735 }
1736
1737 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1738 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1739 err_code |= ERR_ALERT | ERR_ABORT;
1740 goto out;
1741 }
1742
1743 curpeers->next = peers;
1744 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001745 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001746 curpeers->conf.line = linenum;
1747 curpeers->last_change = now.tv_sec;
1748 curpeers->id = strdup(args[1]);
1749 }
1750 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001751 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001752 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001753 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001754
1755 if (!*args[2]) {
1756 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1757 file, linenum, args[0]);
1758 err_code |= ERR_ALERT | ERR_FATAL;
1759 goto out;
1760 }
1761
1762 err = invalid_char(args[1]);
1763 if (err) {
1764 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1765 file, linenum, *err, args[1]);
1766 err_code |= ERR_ALERT | ERR_FATAL;
1767 goto out;
1768 }
1769
1770 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1771 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1772 err_code |= ERR_ALERT | ERR_ABORT;
1773 goto out;
1774 }
1775
1776 /* the peers are linked backwards first */
1777 curpeers->count++;
1778 newpeer->next = curpeers->remote;
1779 curpeers->remote = newpeer;
1780 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001781 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001782 newpeer->conf.line = linenum;
1783
1784 newpeer->last_change = now.tv_sec;
1785 newpeer->id = strdup(args[1]);
1786
Willy Tarreau902636f2013-03-10 19:44:48 +01001787 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001788 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001789 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001790 err_code |= ERR_ALERT | ERR_FATAL;
1791 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001792 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001793
1794 proto = protocol_by_family(sk->ss_family);
1795 if (!proto || !proto->connect) {
1796 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1797 file, linenum, args[0], args[1]);
1798 err_code |= ERR_ALERT | ERR_FATAL;
1799 goto out;
1800 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001801
1802 if (port1 != port2) {
1803 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1804 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001805 err_code |= ERR_ALERT | ERR_FATAL;
1806 goto out;
1807 }
1808
Willy Tarreau2aa38802013-02-20 19:20:59 +01001809 if (!port1) {
1810 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1811 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001812 err_code |= ERR_ALERT | ERR_FATAL;
1813 goto out;
1814 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001815
Emeric Brun32da3c42010-09-23 18:39:19 +02001816 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001817 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001818 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001819 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001820
Emeric Brun32da3c42010-09-23 18:39:19 +02001821 if (strcmp(newpeer->id, localpeer) == 0) {
1822 /* Current is local peer, it define a frontend */
1823 newpeer->local = 1;
1824
1825 if (!curpeers->peers_fe) {
1826 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1827 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1828 err_code |= ERR_ALERT | ERR_ABORT;
1829 goto out;
1830 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001831
Willy Tarreau237250c2011-07-29 01:49:03 +02001832 init_new_proxy(curpeers->peers_fe);
1833 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001834
1835 curpeers->peers_fe->last_change = now.tv_sec;
1836 curpeers->peers_fe->id = strdup(args[1]);
1837 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001838 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001839 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1840 curpeers->peers_fe->timeout.connect = 5000;
1841 curpeers->peers_fe->accept = peer_accept;
1842 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001843 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1844 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001845
1846 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1847
Willy Tarreau902636f2013-03-10 19:44:48 +01001848 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1849 if (errmsg && *errmsg) {
1850 indent_msg(&errmsg, 2);
1851 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001852 }
1853 else
1854 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1855 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001856 err_code |= ERR_FATAL;
1857 goto out;
1858 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001859
1860 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001861 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001862 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1863 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1864 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1865 l->accept = session_accept;
1866 l->handler = process_session;
1867 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1868 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1869 global.maxsock += l->maxconn;
1870 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001871 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001872 else {
1873 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1874 file, linenum, args[0], args[1],
1875 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1876 err_code |= ERR_FATAL;
1877 goto out;
1878 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001879 }
1880 } /* neither "peer" nor "peers" */
1881 else if (*args[0] != 0) {
1882 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1883 err_code |= ERR_ALERT | ERR_FATAL;
1884 goto out;
1885 }
1886
1887out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001888 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001889 return err_code;
1890}
1891
Willy Tarreau3842f002009-06-14 11:39:52 +02001892int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001893{
1894 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001895 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001896 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001897 int rc;
1898 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001899 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001900 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001901 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001902 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001903 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001904
Willy Tarreau977b8e42006-12-29 14:19:17 +01001905 if (!strcmp(args[0], "listen"))
1906 rc = PR_CAP_LISTEN;
1907 else if (!strcmp(args[0], "frontend"))
1908 rc = PR_CAP_FE | PR_CAP_RS;
1909 else if (!strcmp(args[0], "backend"))
1910 rc = PR_CAP_BE | PR_CAP_RS;
1911 else if (!strcmp(args[0], "ruleset"))
1912 rc = PR_CAP_RS;
1913 else
1914 rc = PR_CAP_NONE;
1915
1916 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001917 struct ebpt_node *node;
1918
Willy Tarreaubaaee002006-06-26 02:48:02 +02001919 if (!*args[1]) {
1920 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1921 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1922 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001923 err_code |= ERR_ALERT | ERR_ABORT;
1924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001925 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001926
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001927 err = invalid_char(args[1]);
1928 if (err) {
1929 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1930 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001931 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001932 }
1933
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001934 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1935 curproxy = container_of(node, struct proxy, conf.by_name);
1936
1937 if (strcmp(curproxy->id, args[1]) != 0)
1938 break;
1939
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001940 /*
1941 * If there are two proxies with the same name only following
1942 * combinations are allowed:
1943 *
1944 * listen backend frontend ruleset
1945 * listen - - - -
1946 * backend - - OK -
1947 * frontend - OK - -
1948 * ruleset - - - -
1949 */
1950
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001951 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1952 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001953 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1954 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1955 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001956 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001957 }
1958 }
1959
Willy Tarreaubaaee002006-06-26 02:48:02 +02001960 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1961 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001962 err_code |= ERR_ALERT | ERR_ABORT;
1963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001964 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001965
Willy Tarreau97cb7802010-01-03 20:23:58 +01001966 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001967 curproxy->next = proxy;
1968 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001969 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1970 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001971 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001972 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001973 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001974 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001975
1976 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001977 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001978 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001979
Willy Tarreau4348fad2012-09-20 16:48:07 +02001980 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1981
Willy Tarreau902636f2013-03-10 19:44:48 +01001982 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1983 if (errmsg && *errmsg) {
1984 indent_msg(&errmsg, 2);
1985 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001986 }
1987 else
1988 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1989 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001990 err_code |= ERR_FATAL;
1991 goto out;
1992 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001993
Willy Tarreau4348fad2012-09-20 16:48:07 +02001994 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001995 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001996 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001997 }
1998
1999 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002000 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002001 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002002
Willy Tarreaubaaee002006-06-26 02:48:02 +02002003 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002004 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002005 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002006 curproxy->no_options = defproxy.no_options;
2007 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002008 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01002009 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002010 curproxy->except_net = defproxy.except_net;
2011 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002012 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002013 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002014
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002015 if (defproxy.fwdfor_hdr_len) {
2016 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2017 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2018 }
2019
Willy Tarreaub86db342009-11-30 11:50:16 +01002020 if (defproxy.orgto_hdr_len) {
2021 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2022 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2023 }
2024
Mark Lamourinec2247f02012-01-04 13:02:01 -05002025 if (defproxy.server_id_hdr_len) {
2026 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2027 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2028 }
2029
Willy Tarreau977b8e42006-12-29 14:19:17 +01002030 if (curproxy->cap & PR_CAP_FE) {
2031 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002032 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002033 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002034
2035 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002036 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2037 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002038
2039 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2040 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041
Willy Tarreau977b8e42006-12-29 14:19:17 +01002042 if (curproxy->cap & PR_CAP_BE) {
2043 curproxy->fullconn = defproxy.fullconn;
2044 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002045 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002046
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002047 if (defproxy.check_req) {
2048 curproxy->check_req = calloc(1, defproxy.check_len);
2049 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2050 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002051 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002052
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002053 if (defproxy.expect_str) {
2054 curproxy->expect_str = strdup(defproxy.expect_str);
2055 if (defproxy.expect_regex) {
2056 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002057 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2058 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002059 }
2060 }
2061
Willy Tarreau67402132012-05-31 20:40:20 +02002062 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002063 if (defproxy.cookie_name)
2064 curproxy->cookie_name = strdup(defproxy.cookie_name);
2065 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002066 if (defproxy.cookie_domain)
2067 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002068
Willy Tarreau31936852010-10-06 16:59:56 +02002069 if (defproxy.cookie_maxidle)
2070 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2071
2072 if (defproxy.cookie_maxlife)
2073 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2074
Emeric Brun647caf12009-06-30 17:57:00 +02002075 if (defproxy.rdp_cookie_name)
2076 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2077 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2078
Willy Tarreau01732802007-11-01 22:48:15 +01002079 if (defproxy.url_param_name)
2080 curproxy->url_param_name = strdup(defproxy.url_param_name);
2081 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002082
Benoitaffb4812009-03-25 13:02:10 +01002083 if (defproxy.hh_name)
2084 curproxy->hh_name = strdup(defproxy.hh_name);
2085 curproxy->hh_len = defproxy.hh_len;
2086 curproxy->hh_match_domain = defproxy.hh_match_domain;
2087
Willy Tarreauef9a3602012-12-08 22:29:20 +01002088 if (defproxy.conn_src.iface_name)
2089 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2090 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002091 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002092#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002093 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002094#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002095 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002096
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002097 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002098 if (defproxy.capture_name)
2099 curproxy->capture_name = strdup(defproxy.capture_name);
2100 curproxy->capture_namelen = defproxy.capture_namelen;
2101 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002102 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103
Willy Tarreau977b8e42006-12-29 14:19:17 +01002104 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002105 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002106 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002107 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002108 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002109 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002110 curproxy->mon_net = defproxy.mon_net;
2111 curproxy->mon_mask = defproxy.mon_mask;
2112 if (defproxy.monitor_uri)
2113 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2114 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002115 if (defproxy.defbe.name)
2116 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002117
2118 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002119 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2120 if (curproxy->conf.logformat_string &&
2121 curproxy->conf.logformat_string != default_http_log_format &&
2122 curproxy->conf.logformat_string != default_tcp_log_format &&
2123 curproxy->conf.logformat_string != clf_http_log_format)
2124 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2125
2126 if (defproxy.conf.lfs_file) {
2127 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2128 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2129 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002130 }
2131
2132 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002133 curproxy->timeout.connect = defproxy.timeout.connect;
2134 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002135 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002136 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002137 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002138 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002139 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002140 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002141 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002142 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002143 }
2144
Willy Tarreaubaaee002006-06-26 02:48:02 +02002145 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002146 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002147
2148 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002149 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002150 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002151 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002152 LIST_INIT(&node->list);
2153 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2154 }
2155
Willy Tarreau62a61232013-04-12 18:13:46 +02002156 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2157 if (curproxy->conf.uniqueid_format_string)
2158 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2159
2160 if (defproxy.conf.uif_file) {
2161 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2162 curproxy->conf.uif_line = defproxy.conf.uif_line;
2163 }
William Lallemanda73203e2012-03-12 12:48:57 +01002164
2165 /* copy default header unique id */
2166 if (defproxy.header_unique_id)
2167 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2168
William Lallemand82fe75c2012-10-23 10:25:10 +02002169 /* default compression options */
2170 if (defproxy.comp != NULL) {
2171 curproxy->comp = calloc(1, sizeof(struct comp));
2172 curproxy->comp->algos = defproxy.comp->algos;
2173 curproxy->comp->types = defproxy.comp->types;
2174 }
2175
Willy Tarreaubaaee002006-06-26 02:48:02 +02002176 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002177 curproxy->conf.used_listener_id = EB_ROOT;
2178 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002179
Simon Horman98637e52014-06-20 12:30:16 +09002180 if (defproxy.check_path)
2181 curproxy->check_path = strdup(defproxy.check_path);
2182 if (defproxy.check_command)
2183 curproxy->check_command = strdup(defproxy.check_command);
2184
Willy Tarreau93893792009-07-23 13:19:11 +02002185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002186 }
2187 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2188 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002189 /* FIXME-20070101: we should do this too at the end of the
2190 * config parsing to free all default values.
2191 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002192 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002193 free(defproxy.check_command);
2194 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002195 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002196 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002197 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002198 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002199 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002200 free(defproxy.capture_name);
2201 free(defproxy.monitor_uri);
2202 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002203 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002204 free(defproxy.fwdfor_hdr_name);
2205 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002206 free(defproxy.orgto_hdr_name);
2207 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002208 free(defproxy.server_id_hdr_name);
2209 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002210 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002211 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002212 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002213 free(defproxy.expect_regex);
2214 defproxy.expect_regex = NULL;
2215 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002216
Willy Tarreau62a61232013-04-12 18:13:46 +02002217 if (defproxy.conf.logformat_string != default_http_log_format &&
2218 defproxy.conf.logformat_string != default_tcp_log_format &&
2219 defproxy.conf.logformat_string != clf_http_log_format)
2220 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002221
Willy Tarreau62a61232013-04-12 18:13:46 +02002222 free(defproxy.conf.uniqueid_format_string);
2223 free(defproxy.conf.lfs_file);
2224 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002225
Willy Tarreaua534fea2008-08-03 12:19:50 +02002226 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002227 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002228
Willy Tarreaubaaee002006-06-26 02:48:02 +02002229 /* we cannot free uri_auth because it might already be used */
2230 init_default_instance();
2231 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002232 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2233 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002234 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002235 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002236 }
2237 else if (curproxy == NULL) {
2238 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002239 err_code |= ERR_ALERT | ERR_FATAL;
2240 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002241 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002242
2243 /* update the current file and line being parsed */
2244 curproxy->conf.args.file = curproxy->conf.file;
2245 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002246
2247 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002248 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2249 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2250 if (err_code & ERR_FATAL)
2251 goto out;
2252 }
2253 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002254 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002255 int cur_arg;
2256
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257 if (curproxy == &defproxy) {
2258 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002262 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002263 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002264
Willy Tarreau24709282013-03-10 21:32:12 +01002265 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002266 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002267 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002268 err_code |= ERR_ALERT | ERR_FATAL;
2269 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002271
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002272 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002273
2274 /* use default settings for unix sockets */
2275 bind_conf->ux.uid = global.unix_bind.ux.uid;
2276 bind_conf->ux.gid = global.unix_bind.ux.gid;
2277 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002278
2279 /* NOTE: the following line might create several listeners if there
2280 * are comma-separated IPs or port ranges. So all further processing
2281 * will have to be applied to all listeners created after last_listen.
2282 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002283 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2284 if (errmsg && *errmsg) {
2285 indent_msg(&errmsg, 2);
2286 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002287 }
2288 else
2289 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2290 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
2293 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002294
Willy Tarreau4348fad2012-09-20 16:48:07 +02002295 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2296 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002297 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002298 }
2299
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002300 cur_arg = 2;
2301 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002302 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002303 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002304 char *err;
2305
Willy Tarreau26982662012-09-12 23:17:10 +02002306 kw = bind_find_kw(args[cur_arg]);
2307 if (kw) {
2308 char *err = NULL;
2309 int code;
2310
2311 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002312 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2313 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002314 cur_arg += 1 + kw->skip ;
2315 err_code |= ERR_ALERT | ERR_FATAL;
2316 goto out;
2317 }
2318
Willy Tarreau4348fad2012-09-20 16:48:07 +02002319 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002320 err_code |= code;
2321
2322 if (code) {
2323 if (err && *err) {
2324 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002325 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002326 }
2327 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002328 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2329 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002330 if (code & ERR_FATAL) {
2331 free(err);
2332 cur_arg += 1 + kw->skip;
2333 goto out;
2334 }
2335 }
2336 free(err);
2337 cur_arg += 1 + kw->skip;
2338 continue;
2339 }
2340
Willy Tarreau8638f482012-09-18 18:01:17 +02002341 err = NULL;
2342 if (!bind_dumped) {
2343 bind_dump_kws(&err);
2344 indent_msg(&err, 4);
2345 bind_dumped = 1;
2346 }
2347
2348 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2349 file, linenum, args[0], args[1], args[cur_arg],
2350 err ? " Registered keywords :" : "", err ? err : "");
2351 free(err);
2352
Willy Tarreau93893792009-07-23 13:19:11 +02002353 err_code |= ERR_ALERT | ERR_FATAL;
2354 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002355 }
Willy Tarreau93893792009-07-23 13:19:11 +02002356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357 }
2358 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002359 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2361 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002365 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002366 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002367
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 /* flush useless bits */
2369 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002372 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002373 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002374 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002375
Willy Tarreau1c47f852006-07-09 08:22:27 +02002376 if (!*args[1]) {
2377 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2378 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002379 err_code |= ERR_ALERT | ERR_FATAL;
2380 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002381 }
2382
Willy Tarreaua534fea2008-08-03 12:19:50 +02002383 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002384 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002385 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002386 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002387 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2388
Willy Tarreau93893792009-07-23 13:19:11 +02002389 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002390 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2392 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2393 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2394 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2395 else {
2396 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 }
2400 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002401 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002402 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002403
2404 if (curproxy == &defproxy) {
2405 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2406 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002407 err_code |= ERR_ALERT | ERR_FATAL;
2408 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002409 }
2410
2411 if (!*args[1]) {
2412 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2413 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002414 err_code |= ERR_ALERT | ERR_FATAL;
2415 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002416 }
2417
2418 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002419 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002420
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002421 if (curproxy->uuid <= 0) {
2422 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002423 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_ALERT | ERR_FATAL;
2425 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002426 }
2427
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002428 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2429 if (node) {
2430 struct proxy *target = container_of(node, struct proxy, conf.id);
2431 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2432 file, linenum, proxy_type_str(curproxy), curproxy->id,
2433 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2434 err_code |= ERR_ALERT | ERR_FATAL;
2435 goto out;
2436 }
2437 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002438 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002439 else if (!strcmp(args[0], "description")) {
2440 int i, len=0;
2441 char *d;
2442
Cyril Bonté99ed3272010-01-24 23:29:44 +01002443 if (curproxy == &defproxy) {
2444 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2445 file, linenum, args[0]);
2446 err_code |= ERR_ALERT | ERR_FATAL;
2447 goto out;
2448 }
2449
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002450 if (!*args[1]) {
2451 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2452 file, linenum, args[0]);
2453 return -1;
2454 }
2455
Willy Tarreau348acfe2014-04-14 15:00:39 +02002456 for (i = 1; *args[i]; i++)
2457 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002458
2459 d = (char *)calloc(1, len);
2460 curproxy->desc = d;
2461
Willy Tarreau348acfe2014-04-14 15:00:39 +02002462 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2463 for (i = 2; *args[i]; i++)
2464 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002465
2466 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2468 curproxy->state = PR_STSTOPPED;
2469 }
2470 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2471 curproxy->state = PR_STNEW;
2472 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002473 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2474 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002475 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002476
2477 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002478 unsigned int low, high;
2479
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002480 if (strcmp(args[cur_arg], "all") == 0) {
2481 set = 0;
2482 break;
2483 }
2484 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002485 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002486 }
2487 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002488 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002489 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002490 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002491 char *dash = strchr(args[cur_arg], '-');
2492
2493 low = high = str2uic(args[cur_arg]);
2494 if (dash)
2495 high = str2uic(dash + 1);
2496
2497 if (high < low) {
2498 unsigned int swap = low;
2499 low = high;
2500 high = swap;
2501 }
2502
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002503 if (low < 1 || high > LONGBITS) {
2504 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2505 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002506 err_code |= ERR_ALERT | ERR_FATAL;
2507 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002508 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002509 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002510 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002511 }
2512 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002513 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2514 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002515 err_code |= ERR_ALERT | ERR_FATAL;
2516 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002517 }
2518 cur_arg++;
2519 }
2520 curproxy->bind_proc = set;
2521 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002522 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002523 if (curproxy == &defproxy) {
2524 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002525 err_code |= ERR_ALERT | ERR_FATAL;
2526 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002527 }
2528
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002529 err = invalid_char(args[1]);
2530 if (err) {
2531 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2532 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002533 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002534 }
2535
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002536 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002537 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2538 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002539 err_code |= ERR_ALERT | ERR_FATAL;
2540 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002541 }
2542 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2544 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545
Willy Tarreau977b8e42006-12-29 14:19:17 +01002546 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002547 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002548
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549 if (*(args[1]) == 0) {
2550 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2551 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002552 err_code |= ERR_ALERT | ERR_FATAL;
2553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002554 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002555
Willy Tarreau67402132012-05-31 20:40:20 +02002556 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002557 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002558 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002559 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 curproxy->cookie_name = strdup(args[1]);
2561 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002562
Willy Tarreaubaaee002006-06-26 02:48:02 +02002563 cur_arg = 2;
2564 while (*(args[cur_arg])) {
2565 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002566 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 }
2568 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002569 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 }
2571 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002572 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002573 }
2574 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002575 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 }
2577 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002578 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002580 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002581 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002582 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002584 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002586 else if (!strcmp(args[cur_arg], "httponly")) {
2587 curproxy->ck_opts |= PR_CK_HTTPONLY;
2588 }
2589 else if (!strcmp(args[cur_arg], "secure")) {
2590 curproxy->ck_opts |= PR_CK_SECURE;
2591 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002592 else if (!strcmp(args[cur_arg], "domain")) {
2593 if (!*args[cur_arg + 1]) {
2594 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2595 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002596 err_code |= ERR_ALERT | ERR_FATAL;
2597 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002598 }
2599
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002600 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002601 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002602 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2603 " dots nor does not start with a dot."
2604 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002605 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002606 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002607 }
2608
2609 err = invalid_domainchar(args[cur_arg + 1]);
2610 if (err) {
2611 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2612 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002613 err_code |= ERR_ALERT | ERR_FATAL;
2614 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002615 }
2616
Willy Tarreau68a897b2009-12-03 23:28:34 +01002617 if (!curproxy->cookie_domain) {
2618 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2619 } else {
2620 /* one domain was already specified, add another one by
2621 * building the string which will be returned along with
2622 * the cookie.
2623 */
2624 char *new_ptr;
2625 int new_len = strlen(curproxy->cookie_domain) +
2626 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2627 new_ptr = malloc(new_len);
2628 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2629 free(curproxy->cookie_domain);
2630 curproxy->cookie_domain = new_ptr;
2631 }
Willy Tarreau31936852010-10-06 16:59:56 +02002632 cur_arg++;
2633 }
2634 else if (!strcmp(args[cur_arg], "maxidle")) {
2635 unsigned int maxidle;
2636 const char *res;
2637
2638 if (!*args[cur_arg + 1]) {
2639 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2640 file, linenum, args[cur_arg]);
2641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
2643 }
2644
2645 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2646 if (res) {
2647 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2648 file, linenum, *res, args[cur_arg]);
2649 err_code |= ERR_ALERT | ERR_FATAL;
2650 goto out;
2651 }
2652 curproxy->cookie_maxidle = maxidle;
2653 cur_arg++;
2654 }
2655 else if (!strcmp(args[cur_arg], "maxlife")) {
2656 unsigned int maxlife;
2657 const char *res;
2658
2659 if (!*args[cur_arg + 1]) {
2660 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2661 file, linenum, args[cur_arg]);
2662 err_code |= ERR_ALERT | ERR_FATAL;
2663 goto out;
2664 }
2665
2666 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2667 if (res) {
2668 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2669 file, linenum, *res, args[cur_arg]);
2670 err_code |= ERR_ALERT | ERR_FATAL;
2671 goto out;
2672 }
2673 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002674 cur_arg++;
2675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002677 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 +02002678 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002679 err_code |= ERR_ALERT | ERR_FATAL;
2680 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002681 }
2682 cur_arg++;
2683 }
Willy Tarreau67402132012-05-31 20:40:20 +02002684 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002685 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2686 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002687 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002688 }
2689
Willy Tarreau67402132012-05-31 20:40:20 +02002690 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2692 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002693 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002694 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002695
Willy Tarreau67402132012-05-31 20:40:20 +02002696 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002697 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2698 file, linenum);
2699 err_code |= ERR_ALERT | ERR_FATAL;
2700 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002701 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman98637e52014-06-20 12:30:16 +09002702 else if (!strcmp(args[0], "external-check")) {
2703 if (*(args[1]) == 0) {
2704 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2705 file, linenum, args[0]);
2706 err_code |= ERR_ALERT | ERR_FATAL;
2707 goto out;
2708 }
2709
2710 if (!strcmp(args[1], "command")) {
2711 if (*(args[1]) == 0) {
2712 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2713 file, linenum, args[1]);
2714 err_code |= ERR_ALERT | ERR_FATAL;
2715 goto out;
2716 }
2717 free(curproxy->check_command);
2718 curproxy->check_command = strdup(args[2]);
2719 }
2720 else if (!strcmp(args[1], "path")) {
2721 if (*(args[1]) == 0) {
2722 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2723 file, linenum, args[1]);
2724 err_code |= ERR_ALERT | ERR_FATAL;
2725 goto out;
2726 }
2727 free(curproxy->check_path);
2728 curproxy->check_path = strdup(args[2]);
2729 }
2730 else {
2731 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
2732 file, linenum, args[1]);
2733 err_code |= ERR_ALERT | ERR_FATAL;
2734 goto out;
2735 }
2736 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002737 else if (!strcmp(args[0], "persist")) { /* persist */
2738 if (*(args[1]) == 0) {
2739 Alert("parsing [%s:%d] : missing persist method.\n",
2740 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002743 }
2744
2745 if (!strncmp(args[1], "rdp-cookie", 10)) {
2746 curproxy->options2 |= PR_O2_RDPC_PRST;
2747
Emeric Brunb982a3d2010-01-04 15:45:53 +01002748 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002749 const char *beg, *end;
2750
2751 beg = args[1] + 11;
2752 end = strchr(beg, ')');
2753
2754 if (!end || end == beg) {
2755 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2756 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002759 }
2760
2761 free(curproxy->rdp_cookie_name);
2762 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2763 curproxy->rdp_cookie_len = end-beg;
2764 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002765 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002766 free(curproxy->rdp_cookie_name);
2767 curproxy->rdp_cookie_name = strdup("msts");
2768 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2769 }
2770 else { /* syntax */
2771 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2772 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002773 err_code |= ERR_ALERT | ERR_FATAL;
2774 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002775 }
2776 }
2777 else {
2778 Alert("parsing [%s:%d] : unknown persist method.\n",
2779 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002780 err_code |= ERR_ALERT | ERR_FATAL;
2781 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002782 }
2783 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002784 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002785 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002786
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002787 if (curproxy == &defproxy) {
2788 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2789 err_code |= ERR_ALERT | ERR_FATAL;
2790 goto out;
2791 }
2792
Willy Tarreau977b8e42006-12-29 14:19:17 +01002793 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002794 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002795
Willy Tarreaubaaee002006-06-26 02:48:02 +02002796 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002797 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002798 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002799 err_code |= ERR_ALERT | ERR_FATAL;
2800 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002801 }
2802 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002803 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002804 curproxy->appsession_name = strdup(args[1]);
2805 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2806 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002807 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2808 if (err) {
2809 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2810 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002811 err_code |= ERR_ALERT | ERR_FATAL;
2812 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002813 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002814 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002815
Willy Tarreau51041c72007-09-09 21:56:53 +02002816 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2817 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002818 err_code |= ERR_ALERT | ERR_ABORT;
2819 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002820 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002821
2822 cur_arg = 6;
2823 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002824 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2825 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002826 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002827 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002828 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002829 } else if (!strcmp(args[cur_arg], "prefix")) {
2830 curproxy->options2 |= PR_O2_AS_PFX;
2831 } else if (!strcmp(args[cur_arg], "mode")) {
2832 if (!*args[cur_arg + 1]) {
2833 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2834 file, linenum, args[0], args[cur_arg]);
2835 err_code |= ERR_ALERT | ERR_FATAL;
2836 goto out;
2837 }
2838
2839 cur_arg++;
2840 if (!strcmp(args[cur_arg], "query-string")) {
2841 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2842 curproxy->options2 |= PR_O2_AS_M_QS;
2843 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2844 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2845 curproxy->options2 |= PR_O2_AS_M_PP;
2846 } else {
2847 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2848 err_code |= ERR_ALERT | ERR_FATAL;
2849 goto out;
2850 }
2851 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002852 cur_arg++;
2853 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002854 } /* Url App Session */
2855 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002856 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002857 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002858
Willy Tarreaubaaee002006-06-26 02:48:02 +02002859 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002860 if (curproxy == &defproxy) {
2861 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2862 err_code |= ERR_ALERT | ERR_FATAL;
2863 goto out;
2864 }
2865
Willy Tarreaubaaee002006-06-26 02:48:02 +02002866 if (*(args[4]) == 0) {
2867 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2868 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002869 err_code |= ERR_ALERT | ERR_FATAL;
2870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002871 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002872 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002873 curproxy->capture_name = strdup(args[2]);
2874 curproxy->capture_namelen = strlen(curproxy->capture_name);
2875 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002876 curproxy->to_log |= LW_COOKIE;
2877 }
2878 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2879 struct cap_hdr *hdr;
2880
2881 if (curproxy == &defproxy) {
2882 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 +02002883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002885 }
2886
2887 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2888 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2889 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002890 err_code |= ERR_ALERT | ERR_FATAL;
2891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002892 }
2893
2894 hdr = calloc(sizeof(struct cap_hdr), 1);
2895 hdr->next = curproxy->req_cap;
2896 hdr->name = strdup(args[3]);
2897 hdr->namelen = strlen(args[3]);
2898 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002899 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002900 hdr->index = curproxy->nb_req_cap++;
2901 curproxy->req_cap = hdr;
2902 curproxy->to_log |= LW_REQHDR;
2903 }
2904 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2905 struct cap_hdr *hdr;
2906
2907 if (curproxy == &defproxy) {
2908 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 +02002909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002911 }
2912
2913 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2914 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2915 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002918 }
2919 hdr = calloc(sizeof(struct cap_hdr), 1);
2920 hdr->next = curproxy->rsp_cap;
2921 hdr->name = strdup(args[3]);
2922 hdr->namelen = strlen(args[3]);
2923 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002924 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002925 hdr->index = curproxy->nb_rsp_cap++;
2926 curproxy->rsp_cap = hdr;
2927 curproxy->to_log |= LW_RSPHDR;
2928 }
2929 else {
2930 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2931 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002932 err_code |= ERR_ALERT | ERR_FATAL;
2933 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002934 }
2935 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002936 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002937 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002938 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002939
Willy Tarreaubaaee002006-06-26 02:48:02 +02002940 if (*(args[1]) == 0) {
2941 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2942 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002945 }
2946 curproxy->conn_retries = atol(args[1]);
2947 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002948 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002949 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002950
2951 if (curproxy == &defproxy) {
2952 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2953 err_code |= ERR_ALERT | ERR_FATAL;
2954 goto out;
2955 }
2956
Willy Tarreau20b0de52012-12-24 15:45:22 +01002957 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2958 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2959 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2960 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002961 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002962 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2963 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 +01002964 file, linenum, args[0]);
2965 err_code |= ERR_WARN;
2966 }
2967
Willy Tarreauff011f22011-01-06 17:51:27 +01002968 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002969
Willy Tarreauff011f22011-01-06 17:51:27 +01002970 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002971 err_code |= ERR_ALERT | ERR_ABORT;
2972 goto out;
2973 }
2974
Willy Tarreau5002f572014-04-23 01:32:02 +02002975 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002976 err_code |= warnif_cond_conflicts(rule->cond,
2977 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2978 file, linenum);
2979
Willy Tarreauff011f22011-01-06 17:51:27 +01002980 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002981 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002982 else if (!strcmp(args[0], "http-response")) { /* response access control */
2983 struct http_res_rule *rule;
2984
2985 if (curproxy == &defproxy) {
2986 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
2989 }
2990
2991 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2992 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2993 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2994 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2995 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2996 file, linenum, args[0]);
2997 err_code |= ERR_WARN;
2998 }
2999
3000 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3001
3002 if (!rule) {
3003 err_code |= ERR_ALERT | ERR_ABORT;
3004 goto out;
3005 }
3006
3007 err_code |= warnif_cond_conflicts(rule->cond,
3008 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3009 file, linenum);
3010
3011 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3012 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003013 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3014 /* set the header name and length into the proxy structure */
3015 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3016 err_code |= ERR_WARN;
3017
3018 if (!*args[1]) {
3019 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3020 file, linenum, args[0]);
3021 err_code |= ERR_ALERT | ERR_FATAL;
3022 goto out;
3023 }
3024
3025 /* set the desired header name */
3026 free(curproxy->server_id_hdr_name);
3027 curproxy->server_id_hdr_name = strdup(args[1]);
3028 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3029 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003030 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003031 struct http_req_rule *rule;
3032
Willy Tarreaub099aca2008-10-12 17:26:37 +02003033 if (curproxy == &defproxy) {
3034 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003037 }
3038
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003039 /* emulate "block" using "http-request block". Since these rules are supposed to
3040 * be processed before all http-request rules, we put them into their own list
3041 * and will insert them at the end.
3042 */
3043 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3044 if (!rule) {
3045 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003046 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003047 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003048 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3049 err_code |= warnif_cond_conflicts(rule->cond,
3050 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3051 file, linenum);
3052 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003053
3054 if (!already_warned(WARN_BLOCK_DEPRECATED))
3055 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]);
3056
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003057 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003058 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003059 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003060
Cyril Bonté99ed3272010-01-24 23:29:44 +01003061 if (curproxy == &defproxy) {
3062 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3063 err_code |= ERR_ALERT | ERR_FATAL;
3064 goto out;
3065 }
3066
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003067 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003068 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3069 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003070 err_code |= ERR_ALERT | ERR_FATAL;
3071 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003072 }
3073
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003074 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003075 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003076 err_code |= warnif_cond_conflicts(rule->cond,
3077 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3078 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003079 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003080 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003081 struct switching_rule *rule;
3082
Willy Tarreaub099aca2008-10-12 17:26:37 +02003083 if (curproxy == &defproxy) {
3084 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003085 err_code |= ERR_ALERT | ERR_FATAL;
3086 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003087 }
3088
Willy Tarreau55ea7572007-06-17 19:56:27 +02003089 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003090 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003091
3092 if (*(args[1]) == 0) {
3093 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003096 }
3097
Willy Tarreauf51658d2014-04-23 01:21:56 +02003098 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3099 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3100 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3101 file, linenum, errmsg);
3102 err_code |= ERR_ALERT | ERR_FATAL;
3103 goto out;
3104 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003105
Willy Tarreauf51658d2014-04-23 01:21:56 +02003106 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003107 }
3108
3109 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3110 rule->cond = cond;
3111 rule->be.name = strdup(args[1]);
3112 LIST_INIT(&rule->list);
3113 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3114 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003115 else if (strcmp(args[0], "use-server") == 0) {
3116 struct server_rule *rule;
3117
3118 if (curproxy == &defproxy) {
3119 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
3122 }
3123
3124 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3125 err_code |= ERR_WARN;
3126
3127 if (*(args[1]) == 0) {
3128 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3129 err_code |= ERR_ALERT | ERR_FATAL;
3130 goto out;
3131 }
3132
3133 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3134 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3135 file, linenum, args[0]);
3136 err_code |= ERR_ALERT | ERR_FATAL;
3137 goto out;
3138 }
3139
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003140 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3141 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3142 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003143 err_code |= ERR_ALERT | ERR_FATAL;
3144 goto out;
3145 }
3146
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003147 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003148
3149 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3150 rule->cond = cond;
3151 rule->srv.name = strdup(args[1]);
3152 LIST_INIT(&rule->list);
3153 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3154 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3155 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003156 else if ((!strcmp(args[0], "force-persist")) ||
3157 (!strcmp(args[0], "ignore-persist"))) {
3158 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003159
3160 if (curproxy == &defproxy) {
3161 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3162 err_code |= ERR_ALERT | ERR_FATAL;
3163 goto out;
3164 }
3165
3166 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3167 err_code |= ERR_WARN;
3168
Willy Tarreauef6494c2010-01-28 17:12:36 +01003169 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003170 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3171 file, linenum, args[0]);
3172 err_code |= ERR_ALERT | ERR_FATAL;
3173 goto out;
3174 }
3175
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003176 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3177 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3178 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003179 err_code |= ERR_ALERT | ERR_FATAL;
3180 goto out;
3181 }
3182
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003183 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3184 * where force-persist is applied.
3185 */
3186 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003187
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003188 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003189 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003190 if (!strcmp(args[0], "force-persist")) {
3191 rule->type = PERSIST_TYPE_FORCE;
3192 } else {
3193 rule->type = PERSIST_TYPE_IGNORE;
3194 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003195 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003196 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003197 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003198 else if (!strcmp(args[0], "stick-table")) {
3199 int myidx = 1;
3200
Emeric Brun32da3c42010-09-23 18:39:19 +02003201 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003202 curproxy->table.type = (unsigned int)-1;
3203 while (*args[myidx]) {
3204 const char *err;
3205
3206 if (strcmp(args[myidx], "size") == 0) {
3207 myidx++;
3208 if (!*(args[myidx])) {
3209 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3210 file, linenum, args[myidx-1]);
3211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
3213 }
3214 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3215 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3216 file, linenum, *err, args[myidx-1]);
3217 err_code |= ERR_ALERT | ERR_FATAL;
3218 goto out;
3219 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003220 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003221 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003222 else if (strcmp(args[myidx], "peers") == 0) {
3223 myidx++;
Godbach50523162013-12-11 19:48:57 +08003224 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003225 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3226 file, linenum, args[myidx-1]);
3227 err_code |= ERR_ALERT | ERR_FATAL;
3228 goto out;
Godbach50523162013-12-11 19:48:57 +08003229 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003230 curproxy->table.peers.name = strdup(args[myidx++]);
3231 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003232 else if (strcmp(args[myidx], "expire") == 0) {
3233 myidx++;
3234 if (!*(args[myidx])) {
3235 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3236 file, linenum, args[myidx-1]);
3237 err_code |= ERR_ALERT | ERR_FATAL;
3238 goto out;
3239 }
3240 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3241 if (err) {
3242 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3243 file, linenum, *err, args[myidx-1]);
3244 err_code |= ERR_ALERT | ERR_FATAL;
3245 goto out;
3246 }
3247 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003248 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003249 }
3250 else if (strcmp(args[myidx], "nopurge") == 0) {
3251 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003252 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003253 }
3254 else if (strcmp(args[myidx], "type") == 0) {
3255 myidx++;
3256 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3257 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3258 file, linenum, args[myidx]);
3259 err_code |= ERR_ALERT | ERR_FATAL;
3260 goto out;
3261 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003262 /* myidx already points to next arg */
3263 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003264 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003265 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003266 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003267
3268 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003269 nw = args[myidx];
3270 while (*nw) {
3271 /* the "store" keyword supports a comma-separated list */
3272 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003273 sa = NULL; /* store arg */
3274 while (*nw && *nw != ',') {
3275 if (*nw == '(') {
3276 *nw = 0;
3277 sa = ++nw;
3278 while (*nw != ')') {
3279 if (!*nw) {
3280 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3281 file, linenum, args[0], cw);
3282 err_code |= ERR_ALERT | ERR_FATAL;
3283 goto out;
3284 }
3285 nw++;
3286 }
3287 *nw = '\0';
3288 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003289 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003290 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003291 if (*nw)
3292 *nw++ = '\0';
3293 type = stktable_get_data_type(cw);
3294 if (type < 0) {
3295 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3296 file, linenum, args[0], cw);
3297 err_code |= ERR_ALERT | ERR_FATAL;
3298 goto out;
3299 }
Willy Tarreauac782882010-06-20 10:41:54 +02003300
3301 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3302 switch (err) {
3303 case PE_NONE: break;
3304 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003305 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3306 file, linenum, args[0], cw);
3307 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003308 break;
3309
3310 case PE_ARG_MISSING:
3311 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3312 file, linenum, args[0], cw);
3313 err_code |= ERR_ALERT | ERR_FATAL;
3314 goto out;
3315
3316 case PE_ARG_NOT_USED:
3317 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3318 file, linenum, args[0], cw);
3319 err_code |= ERR_ALERT | ERR_FATAL;
3320 goto out;
3321
3322 default:
3323 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3324 file, linenum, args[0], cw);
3325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003327 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003328 }
3329 myidx++;
3330 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003331 else {
3332 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3333 file, linenum, args[myidx]);
3334 err_code |= ERR_ALERT | ERR_FATAL;
3335 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003336 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003337 }
3338
3339 if (!curproxy->table.size) {
3340 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3341 file, linenum);
3342 err_code |= ERR_ALERT | ERR_FATAL;
3343 goto out;
3344 }
3345
3346 if (curproxy->table.type == (unsigned int)-1) {
3347 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3348 file, linenum);
3349 err_code |= ERR_ALERT | ERR_FATAL;
3350 goto out;
3351 }
3352 }
3353 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003354 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003355 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003356 int myidx = 0;
3357 const char *name = NULL;
3358 int flags;
3359
3360 if (curproxy == &defproxy) {
3361 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3362 err_code |= ERR_ALERT | ERR_FATAL;
3363 goto out;
3364 }
3365
3366 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3367 err_code |= ERR_WARN;
3368 goto out;
3369 }
3370
3371 myidx++;
3372 if ((strcmp(args[myidx], "store") == 0) ||
3373 (strcmp(args[myidx], "store-request") == 0)) {
3374 myidx++;
3375 flags = STK_IS_STORE;
3376 }
3377 else if (strcmp(args[myidx], "store-response") == 0) {
3378 myidx++;
3379 flags = STK_IS_STORE | STK_ON_RSP;
3380 }
3381 else if (strcmp(args[myidx], "match") == 0) {
3382 myidx++;
3383 flags = STK_IS_MATCH;
3384 }
3385 else if (strcmp(args[myidx], "on") == 0) {
3386 myidx++;
3387 flags = STK_IS_MATCH | STK_IS_STORE;
3388 }
3389 else {
3390 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
3393 }
3394
3395 if (*(args[myidx]) == 0) {
3396 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3397 err_code |= ERR_ALERT | ERR_FATAL;
3398 goto out;
3399 }
3400
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003401 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003402 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003403 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003404 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
3407 }
3408
3409 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003410 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3411 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3412 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003413 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003414 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003415 goto out;
3416 }
3417 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003418 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3419 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3420 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003421 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003422 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003423 goto out;
3424 }
3425 }
3426
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003427 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003428 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003429
Emeric Brunb982a3d2010-01-04 15:45:53 +01003430 if (strcmp(args[myidx], "table") == 0) {
3431 myidx++;
3432 name = args[myidx++];
3433 }
3434
Willy Tarreauef6494c2010-01-28 17:12:36 +01003435 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003436 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3437 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3438 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003439 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003440 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003441 goto out;
3442 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003443 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003444 else if (*(args[myidx])) {
3445 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3446 file, linenum, args[0], args[myidx]);
3447 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003448 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003449 goto out;
3450 }
Emeric Brun97679e72010-09-23 17:56:44 +02003451 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003452 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003453 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003454 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003455
Emeric Brunb982a3d2010-01-04 15:45:53 +01003456 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3457 rule->cond = cond;
3458 rule->expr = expr;
3459 rule->flags = flags;
3460 rule->table.name = name ? strdup(name) : NULL;
3461 LIST_INIT(&rule->list);
3462 if (flags & STK_ON_RSP)
3463 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3464 else
3465 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3466 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003467 else if (!strcmp(args[0], "stats")) {
3468 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3469 curproxy->uri_auth = NULL; /* we must detach from the default config */
3470
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003471 if (!*args[1]) {
3472 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003473 } else if (!strcmp(args[1], "admin")) {
3474 struct stats_admin_rule *rule;
3475
3476 if (curproxy == &defproxy) {
3477 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3478 err_code |= ERR_ALERT | ERR_FATAL;
3479 goto out;
3480 }
3481
3482 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3483 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3484 err_code |= ERR_ALERT | ERR_ABORT;
3485 goto out;
3486 }
3487
3488 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3489 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3490 file, linenum, args[0], args[1]);
3491 err_code |= ERR_ALERT | ERR_FATAL;
3492 goto out;
3493 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003494 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3495 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3496 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003497 err_code |= ERR_ALERT | ERR_FATAL;
3498 goto out;
3499 }
3500
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003501 err_code |= warnif_cond_conflicts(cond,
3502 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3503 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003504
3505 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3506 rule->cond = cond;
3507 LIST_INIT(&rule->list);
3508 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003509 } else if (!strcmp(args[1], "uri")) {
3510 if (*(args[2]) == 0) {
3511 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003512 err_code |= ERR_ALERT | ERR_FATAL;
3513 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003514 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3515 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003516 err_code |= ERR_ALERT | ERR_ABORT;
3517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003518 }
3519 } else if (!strcmp(args[1], "realm")) {
3520 if (*(args[2]) == 0) {
3521 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003522 err_code |= ERR_ALERT | ERR_FATAL;
3523 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3525 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003526 err_code |= ERR_ALERT | ERR_ABORT;
3527 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003529 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003530 unsigned interval;
3531
3532 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3533 if (err) {
3534 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3535 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003538 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3539 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003540 err_code |= ERR_ALERT | ERR_ABORT;
3541 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003542 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003543 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003544 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003545
3546 if (curproxy == &defproxy) {
3547 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3548 err_code |= ERR_ALERT | ERR_FATAL;
3549 goto out;
3550 }
3551
3552 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3553 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3554 err_code |= ERR_ALERT | ERR_ABORT;
3555 goto out;
3556 }
3557
Willy Tarreauff011f22011-01-06 17:51:27 +01003558 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3559 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003560 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3561 file, linenum, args[0]);
3562 err_code |= ERR_WARN;
3563 }
3564
Willy Tarreauff011f22011-01-06 17:51:27 +01003565 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003566
Willy Tarreauff011f22011-01-06 17:51:27 +01003567 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003568 err_code |= ERR_ALERT | ERR_ABORT;
3569 goto out;
3570 }
3571
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003572 err_code |= warnif_cond_conflicts(rule->cond,
3573 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3574 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003575 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003576
Willy Tarreaubaaee002006-06-26 02:48:02 +02003577 } else if (!strcmp(args[1], "auth")) {
3578 if (*(args[2]) == 0) {
3579 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003580 err_code |= ERR_ALERT | ERR_FATAL;
3581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3583 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003584 err_code |= ERR_ALERT | ERR_ABORT;
3585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003586 }
3587 } else if (!strcmp(args[1], "scope")) {
3588 if (*(args[2]) == 0) {
3589 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003590 err_code |= ERR_ALERT | ERR_FATAL;
3591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003592 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3593 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003594 err_code |= ERR_ALERT | ERR_ABORT;
3595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003596 }
3597 } else if (!strcmp(args[1], "enable")) {
3598 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3599 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003600 err_code |= ERR_ALERT | ERR_ABORT;
3601 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003602 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003603 } else if (!strcmp(args[1], "hide-version")) {
3604 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3605 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_ALERT | ERR_ABORT;
3607 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003608 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003609 } else if (!strcmp(args[1], "show-legends")) {
3610 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3611 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3612 err_code |= ERR_ALERT | ERR_ABORT;
3613 goto out;
3614 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003615 } else if (!strcmp(args[1], "show-node")) {
3616
3617 if (*args[2]) {
3618 int i;
3619 char c;
3620
3621 for (i=0; args[2][i]; i++) {
3622 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003623 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3624 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003625 break;
3626 }
3627
3628 if (!i || args[2][i]) {
3629 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3630 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3631 file, linenum, args[0], args[1]);
3632 err_code |= ERR_ALERT | ERR_FATAL;
3633 goto out;
3634 }
3635 }
3636
3637 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3638 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3639 err_code |= ERR_ALERT | ERR_ABORT;
3640 goto out;
3641 }
3642 } else if (!strcmp(args[1], "show-desc")) {
3643 char *desc = NULL;
3644
3645 if (*args[2]) {
3646 int i, len=0;
3647 char *d;
3648
Willy Tarreau348acfe2014-04-14 15:00:39 +02003649 for (i = 2; *args[i]; i++)
3650 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003651
3652 desc = d = (char *)calloc(1, len);
3653
Willy Tarreau348acfe2014-04-14 15:00:39 +02003654 d += snprintf(d, desc + len - d, "%s", args[2]);
3655 for (i = 3; *args[i]; i++)
3656 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003657 }
3658
3659 if (!*args[2] && !global.desc)
3660 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3661 file, linenum, args[1]);
3662 else {
3663 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3664 free(desc);
3665 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3666 err_code |= ERR_ALERT | ERR_ABORT;
3667 goto out;
3668 }
3669 free(desc);
3670 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003671 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003672stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003673 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 +01003674 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003675 err_code |= ERR_ALERT | ERR_FATAL;
3676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003677 }
3678 }
3679 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003680 int optnum;
3681
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003682 if (*(args[1]) == '\0') {
3683 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3684 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003687 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003688
3689 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3690 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003691 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3692 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3693 file, linenum, cfg_opts[optnum].name);
3694 err_code |= ERR_ALERT | ERR_FATAL;
3695 goto out;
3696 }
Willy Tarreau93893792009-07-23 13:19:11 +02003697 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3698 err_code |= ERR_WARN;
3699 goto out;
3700 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003701
Willy Tarreau3842f002009-06-14 11:39:52 +02003702 curproxy->no_options &= ~cfg_opts[optnum].val;
3703 curproxy->options &= ~cfg_opts[optnum].val;
3704
3705 switch (kwm) {
3706 case KWM_STD:
3707 curproxy->options |= cfg_opts[optnum].val;
3708 break;
3709 case KWM_NO:
3710 curproxy->no_options |= cfg_opts[optnum].val;
3711 break;
3712 case KWM_DEF: /* already cleared */
3713 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003714 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003715
Willy Tarreau93893792009-07-23 13:19:11 +02003716 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003717 }
3718 }
3719
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003720 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3721 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003722 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3723 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3724 file, linenum, cfg_opts2[optnum].name);
3725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
3727 }
Willy Tarreau93893792009-07-23 13:19:11 +02003728 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3729 err_code |= ERR_WARN;
3730 goto out;
3731 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003732
Willy Tarreau3842f002009-06-14 11:39:52 +02003733 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3734 curproxy->options2 &= ~cfg_opts2[optnum].val;
3735
3736 switch (kwm) {
3737 case KWM_STD:
3738 curproxy->options2 |= cfg_opts2[optnum].val;
3739 break;
3740 case KWM_NO:
3741 curproxy->no_options2 |= cfg_opts2[optnum].val;
3742 break;
3743 case KWM_DEF: /* already cleared */
3744 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003745 }
Willy Tarreau93893792009-07-23 13:19:11 +02003746 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003747 }
3748 }
3749
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003750 /* HTTP options override each other. They can be cancelled using
3751 * "no option xxx" which only switches to default mode if the mode
3752 * was this one (useful for cancelling options set in defaults
3753 * sections).
3754 */
3755 if (strcmp(args[1], "httpclose") == 0) {
3756 if (kwm == KWM_STD) {
3757 curproxy->options &= ~PR_O_HTTP_MODE;
3758 curproxy->options |= PR_O_HTTP_PCL;
3759 goto out;
3760 }
3761 else if (kwm == KWM_NO) {
3762 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3763 curproxy->options &= ~PR_O_HTTP_MODE;
3764 goto out;
3765 }
3766 }
3767 else if (strcmp(args[1], "forceclose") == 0) {
3768 if (kwm == KWM_STD) {
3769 curproxy->options &= ~PR_O_HTTP_MODE;
3770 curproxy->options |= PR_O_HTTP_FCL;
3771 goto out;
3772 }
3773 else if (kwm == KWM_NO) {
3774 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3775 curproxy->options &= ~PR_O_HTTP_MODE;
3776 goto out;
3777 }
3778 }
3779 else if (strcmp(args[1], "http-server-close") == 0) {
3780 if (kwm == KWM_STD) {
3781 curproxy->options &= ~PR_O_HTTP_MODE;
3782 curproxy->options |= PR_O_HTTP_SCL;
3783 goto out;
3784 }
3785 else if (kwm == KWM_NO) {
3786 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3787 curproxy->options &= ~PR_O_HTTP_MODE;
3788 goto out;
3789 }
3790 }
3791 else if (strcmp(args[1], "http-keep-alive") == 0) {
3792 if (kwm == KWM_STD) {
3793 curproxy->options &= ~PR_O_HTTP_MODE;
3794 curproxy->options |= PR_O_HTTP_KAL;
3795 goto out;
3796 }
3797 else if (kwm == KWM_NO) {
3798 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3799 curproxy->options &= ~PR_O_HTTP_MODE;
3800 goto out;
3801 }
3802 }
3803 else if (strcmp(args[1], "http-tunnel") == 0) {
3804 if (kwm == KWM_STD) {
3805 curproxy->options &= ~PR_O_HTTP_MODE;
3806 curproxy->options |= PR_O_HTTP_TUN;
3807 goto out;
3808 }
3809 else if (kwm == KWM_NO) {
3810 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3811 curproxy->options &= ~PR_O_HTTP_MODE;
3812 goto out;
3813 }
3814 }
3815
Willy Tarreau3842f002009-06-14 11:39:52 +02003816 if (kwm != KWM_STD) {
3817 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003818 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003819 err_code |= ERR_ALERT | ERR_FATAL;
3820 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003821 }
3822
Emeric Brun3a058f32009-06-30 18:26:00 +02003823 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003824 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003825 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003826 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003827 if (*(args[2]) != '\0') {
3828 if (!strcmp(args[2], "clf")) {
3829 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003830 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003831 } else {
3832 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003833 err_code |= ERR_ALERT | ERR_FATAL;
3834 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003835 }
3836 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003837 if (curproxy->conf.logformat_string != default_http_log_format &&
3838 curproxy->conf.logformat_string != default_tcp_log_format &&
3839 curproxy->conf.logformat_string != clf_http_log_format)
3840 free(curproxy->conf.logformat_string);
3841 curproxy->conf.logformat_string = logformat;
3842
3843 free(curproxy->conf.lfs_file);
3844 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3845 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003846 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003847 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003849 if (curproxy->conf.logformat_string != default_http_log_format &&
3850 curproxy->conf.logformat_string != default_tcp_log_format &&
3851 curproxy->conf.logformat_string != clf_http_log_format)
3852 free(curproxy->conf.logformat_string);
3853 curproxy->conf.logformat_string = default_tcp_log_format;
3854
3855 free(curproxy->conf.lfs_file);
3856 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3857 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003858 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 else if (!strcmp(args[1], "tcpka")) {
3860 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003861 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003862 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003863
3864 if (curproxy->cap & PR_CAP_FE)
3865 curproxy->options |= PR_O_TCP_CLI_KA;
3866 if (curproxy->cap & PR_CAP_BE)
3867 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 }
3869 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003870 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_WARN;
3872
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003874 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003875 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003876 curproxy->options2 &= ~PR_O2_CHK_ANY;
3877 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003878 if (!*args[2]) { /* no argument */
3879 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3880 curproxy->check_len = strlen(DEF_CHECK_REQ);
3881 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003882 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003883 curproxy->check_req = (char *)malloc(reqlen);
3884 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003885 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003886 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003887 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003888 if (*args[4])
3889 reqlen += strlen(args[4]);
3890 else
3891 reqlen += strlen("HTTP/1.0");
3892
3893 curproxy->check_req = (char *)malloc(reqlen);
3894 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003895 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003896 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003897 }
3898 else if (!strcmp(args[1], "ssl-hello-chk")) {
3899 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003900 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003901 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003902
Willy Tarreaua534fea2008-08-03 12:19:50 +02003903 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003904 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003905 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003906 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003907 }
Willy Tarreau23677902007-05-08 23:50:35 +02003908 else if (!strcmp(args[1], "smtpchk")) {
3909 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003910 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003911 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003912 curproxy->options2 &= ~PR_O2_CHK_ANY;
3913 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003914
3915 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3916 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3917 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3918 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3919 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3920 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3921 curproxy->check_req = (char *)malloc(reqlen);
3922 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3923 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3924 } else {
3925 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3926 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3927 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3928 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3929 }
3930 }
3931 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003932 else if (!strcmp(args[1], "pgsql-check")) {
3933 /* use PostgreSQL request to check servers' health */
3934 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3935 err_code |= ERR_WARN;
3936
3937 free(curproxy->check_req);
3938 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003939 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003940 curproxy->options2 |= PR_O2_PGSQL_CHK;
3941
3942 if (*(args[2])) {
3943 int cur_arg = 2;
3944
3945 while (*(args[cur_arg])) {
3946 if (strcmp(args[cur_arg], "user") == 0) {
3947 char * packet;
3948 uint32_t packet_len;
3949 uint32_t pv;
3950
3951 /* suboption header - needs additional argument for it */
3952 if (*(args[cur_arg+1]) == 0) {
3953 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3954 file, linenum, args[0], args[1], args[cur_arg]);
3955 err_code |= ERR_ALERT | ERR_FATAL;
3956 goto out;
3957 }
3958
3959 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3960 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3961 pv = htonl(0x30000); /* protocol version 3.0 */
3962
3963 packet = (char*) calloc(1, packet_len);
3964
3965 memcpy(packet + 4, &pv, 4);
3966
3967 /* copy "user" */
3968 memcpy(packet + 8, "user", 4);
3969
3970 /* copy username */
3971 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3972
3973 free(curproxy->check_req);
3974 curproxy->check_req = packet;
3975 curproxy->check_len = packet_len;
3976
3977 packet_len = htonl(packet_len);
3978 memcpy(packet, &packet_len, 4);
3979 cur_arg += 2;
3980 } else {
3981 /* unknown suboption - catchall */
3982 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3983 file, linenum, args[0], args[1]);
3984 err_code |= ERR_ALERT | ERR_FATAL;
3985 goto out;
3986 }
3987 } /* end while loop */
3988 }
3989 }
3990
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003991 else if (!strcmp(args[1], "redis-check")) {
3992 /* use REDIS PING request to check servers' health */
3993 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3994 err_code |= ERR_WARN;
3995
3996 free(curproxy->check_req);
3997 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003998 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003999 curproxy->options2 |= PR_O2_REDIS_CHK;
4000
4001 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4002 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4003 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4004 }
4005
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004006 else if (!strcmp(args[1], "mysql-check")) {
4007 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004008 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4009 err_code |= ERR_WARN;
4010
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004011 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004012 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004013 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004014 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004015
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004016 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004017 * const char mysql40_client_auth_pkt[] = {
4018 * "\x0e\x00\x00" // packet length
4019 * "\x01" // packet number
4020 * "\x00\x00" // client capabilities
4021 * "\x00\x00\x01" // max packet
4022 * "haproxy\x00" // username (null terminated string)
4023 * "\x00" // filler (always 0x00)
4024 * "\x01\x00\x00" // packet length
4025 * "\x00" // packet number
4026 * "\x01" // COM_QUIT command
4027 * };
4028 */
4029
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004030 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4031 * const char mysql41_client_auth_pkt[] = {
4032 * "\x0e\x00\x00\" // packet length
4033 * "\x01" // packet number
4034 * "\x00\x00\x00\x00" // client capabilities
4035 * "\x00\x00\x00\x01" // max packet
4036 * "\x21" // character set (UTF-8)
4037 * char[23] // All zeroes
4038 * "haproxy\x00" // username (null terminated string)
4039 * "\x00" // filler (always 0x00)
4040 * "\x01\x00\x00" // packet length
4041 * "\x00" // packet number
4042 * "\x01" // COM_QUIT command
4043 * };
4044 */
4045
4046
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004047 if (*(args[2])) {
4048 int cur_arg = 2;
4049
4050 while (*(args[cur_arg])) {
4051 if (strcmp(args[cur_arg], "user") == 0) {
4052 char *mysqluser;
4053 int packetlen, reqlen, userlen;
4054
4055 /* suboption header - needs additional argument for it */
4056 if (*(args[cur_arg+1]) == 0) {
4057 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4058 file, linenum, args[0], args[1], args[cur_arg]);
4059 err_code |= ERR_ALERT | ERR_FATAL;
4060 goto out;
4061 }
4062 mysqluser = args[cur_arg + 1];
4063 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004064
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004065 if (*(args[cur_arg+2])) {
4066 if (!strcmp(args[cur_arg+2], "post-41")) {
4067 packetlen = userlen + 7 + 27;
4068 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004069
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004070 free(curproxy->check_req);
4071 curproxy->check_req = (char *)calloc(1, reqlen);
4072 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004073
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004074 snprintf(curproxy->check_req, 4, "%c%c%c",
4075 ((unsigned char) packetlen & 0xff),
4076 ((unsigned char) (packetlen >> 8) & 0xff),
4077 ((unsigned char) (packetlen >> 16) & 0xff));
4078
4079 curproxy->check_req[3] = 1;
4080 curproxy->check_req[5] = 130;
4081 curproxy->check_req[11] = 1;
4082 curproxy->check_req[12] = 33;
4083 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4084 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4085 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4086 cur_arg += 3;
4087 } else {
4088 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
4091 }
4092 } else {
4093 packetlen = userlen + 7;
4094 reqlen = packetlen + 9;
4095
4096 free(curproxy->check_req);
4097 curproxy->check_req = (char *)calloc(1, reqlen);
4098 curproxy->check_len = reqlen;
4099
4100 snprintf(curproxy->check_req, 4, "%c%c%c",
4101 ((unsigned char) packetlen & 0xff),
4102 ((unsigned char) (packetlen >> 8) & 0xff),
4103 ((unsigned char) (packetlen >> 16) & 0xff));
4104
4105 curproxy->check_req[3] = 1;
4106 curproxy->check_req[5] = 128;
4107 curproxy->check_req[8] = 1;
4108 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4109 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4110 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4111 cur_arg += 2;
4112 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004113 } else {
4114 /* unknown suboption - catchall */
4115 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4116 file, linenum, args[0], args[1]);
4117 err_code |= ERR_ALERT | ERR_FATAL;
4118 goto out;
4119 }
4120 } /* end while loop */
4121 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004122 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004123 else if (!strcmp(args[1], "ldap-check")) {
4124 /* use LDAP request to check servers' health */
4125 free(curproxy->check_req);
4126 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004127 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004128 curproxy->options2 |= PR_O2_LDAP_CHK;
4129
4130 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4131 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4132 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4133 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004134 else if (!strcmp(args[1], "tcp-check")) {
4135 /* use raw TCPCHK send/expect to check servers' health */
4136 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4137 err_code |= ERR_WARN;
4138
4139 free(curproxy->check_req);
4140 curproxy->check_req = NULL;
4141 curproxy->options2 &= ~PR_O2_CHK_ANY;
4142 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4143 }
Simon Horman98637e52014-06-20 12:30:16 +09004144 else if (!strcmp(args[1], "external-check")) {
4145 /* excute an external command to check servers' health */
4146 free(curproxy->check_req);
4147 curproxy->check_req = NULL;
4148 curproxy->options2 &= ~PR_O2_CHK_ANY;
4149 curproxy->options2 |= PR_O2_EXT_CHK;
4150 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004151 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004152 int cur_arg;
4153
4154 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4155 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004156 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004157
Willy Tarreau87cf5142011-08-19 22:57:24 +02004158 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004159
4160 free(curproxy->fwdfor_hdr_name);
4161 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4162 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4163
4164 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4165 cur_arg = 2;
4166 while (*(args[cur_arg])) {
4167 if (!strcmp(args[cur_arg], "except")) {
4168 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004169 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004170 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4171 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004172 err_code |= ERR_ALERT | ERR_FATAL;
4173 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004174 }
4175 /* flush useless bits */
4176 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004177 cur_arg += 2;
4178 } else if (!strcmp(args[cur_arg], "header")) {
4179 /* suboption header - needs additional argument for it */
4180 if (*(args[cur_arg+1]) == 0) {
4181 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4182 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004183 err_code |= ERR_ALERT | ERR_FATAL;
4184 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004185 }
4186 free(curproxy->fwdfor_hdr_name);
4187 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4188 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4189 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004190 } else if (!strcmp(args[cur_arg], "if-none")) {
4191 curproxy->options &= ~PR_O_FF_ALWAYS;
4192 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004193 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004194 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004195 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004196 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004197 err_code |= ERR_ALERT | ERR_FATAL;
4198 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004199 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004200 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004201 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004202 else if (!strcmp(args[1], "originalto")) {
4203 int cur_arg;
4204
4205 /* insert x-original-to field, but not for the IP address listed as an except.
4206 * set default options (ie: bitfield, header name, etc)
4207 */
4208
4209 curproxy->options |= PR_O_ORGTO;
4210
4211 free(curproxy->orgto_hdr_name);
4212 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4213 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4214
Willy Tarreau87cf5142011-08-19 22:57:24 +02004215 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004216 cur_arg = 2;
4217 while (*(args[cur_arg])) {
4218 if (!strcmp(args[cur_arg], "except")) {
4219 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004220 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 +02004221 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4222 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004223 err_code |= ERR_ALERT | ERR_FATAL;
4224 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004225 }
4226 /* flush useless bits */
4227 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4228 cur_arg += 2;
4229 } else if (!strcmp(args[cur_arg], "header")) {
4230 /* suboption header - needs additional argument for it */
4231 if (*(args[cur_arg+1]) == 0) {
4232 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4233 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004234 err_code |= ERR_ALERT | ERR_FATAL;
4235 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004236 }
4237 free(curproxy->orgto_hdr_name);
4238 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4239 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4240 cur_arg += 2;
4241 } else {
4242 /* unknown suboption - catchall */
4243 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4244 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004247 }
4248 } /* end while loop */
4249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004250 else {
4251 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004254 }
Willy Tarreau93893792009-07-23 13:19:11 +02004255 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004256 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004257 else if (!strcmp(args[0], "default_backend")) {
4258 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004259 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004260
4261 if (*(args[1]) == 0) {
4262 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004263 err_code |= ERR_ALERT | ERR_FATAL;
4264 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004265 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004266 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004267 curproxy->defbe.name = strdup(args[1]);
4268 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004269 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004270 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004271 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004272
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004273 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4274 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 +01004275 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004276 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004277 /* enable reconnections to dispatch */
4278 curproxy->options |= PR_O_REDISP;
4279 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004280 else if (!strcmp(args[0], "http-check")) {
4281 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004282 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004283
4284 if (strcmp(args[1], "disable-on-404") == 0) {
4285 /* enable a graceful server shutdown on an HTTP 404 response */
4286 curproxy->options |= PR_O_DISABLE404;
4287 }
Willy Tarreauef781042010-01-27 11:53:01 +01004288 else if (strcmp(args[1], "send-state") == 0) {
4289 /* enable emission of the apparent state of a server in HTTP checks */
4290 curproxy->options2 |= PR_O2_CHK_SNDST;
4291 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004292 else if (strcmp(args[1], "expect") == 0) {
4293 const char *ptr_arg;
4294 int cur_arg;
4295
4296 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4297 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4298 err_code |= ERR_ALERT | ERR_FATAL;
4299 goto out;
4300 }
4301
4302 cur_arg = 2;
4303 /* consider exclamation marks, sole or at the beginning of a word */
4304 while (*(ptr_arg = args[cur_arg])) {
4305 while (*ptr_arg == '!') {
4306 curproxy->options2 ^= PR_O2_EXP_INV;
4307 ptr_arg++;
4308 }
4309 if (*ptr_arg)
4310 break;
4311 cur_arg++;
4312 }
4313 /* now ptr_arg points to the beginning of a word past any possible
4314 * exclamation mark, and cur_arg is the argument which holds this word.
4315 */
4316 if (strcmp(ptr_arg, "status") == 0) {
4317 if (!*(args[cur_arg + 1])) {
4318 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4319 file, linenum, args[0], args[1], ptr_arg);
4320 err_code |= ERR_ALERT | ERR_FATAL;
4321 goto out;
4322 }
4323 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004324 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004325 curproxy->expect_str = strdup(args[cur_arg + 1]);
4326 }
4327 else if (strcmp(ptr_arg, "string") == 0) {
4328 if (!*(args[cur_arg + 1])) {
4329 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4330 file, linenum, args[0], args[1], ptr_arg);
4331 err_code |= ERR_ALERT | ERR_FATAL;
4332 goto out;
4333 }
4334 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004335 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004336 curproxy->expect_str = strdup(args[cur_arg + 1]);
4337 }
4338 else if (strcmp(ptr_arg, "rstatus") == 0) {
4339 if (!*(args[cur_arg + 1])) {
4340 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4341 file, linenum, args[0], args[1], ptr_arg);
4342 err_code |= ERR_ALERT | ERR_FATAL;
4343 goto out;
4344 }
4345 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004346 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004347 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004348 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004349 free(curproxy->expect_regex);
4350 curproxy->expect_regex = NULL;
4351 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004352 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004353 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4354 error = NULL;
4355 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4356 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4357 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4358 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004359 err_code |= ERR_ALERT | ERR_FATAL;
4360 goto out;
4361 }
4362 }
4363 else if (strcmp(ptr_arg, "rstring") == 0) {
4364 if (!*(args[cur_arg + 1])) {
4365 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4366 file, linenum, args[0], args[1], ptr_arg);
4367 err_code |= ERR_ALERT | ERR_FATAL;
4368 goto out;
4369 }
4370 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004371 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004372 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004373 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004374 free(curproxy->expect_regex);
4375 curproxy->expect_regex = NULL;
4376 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004377 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004378 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4379 error = NULL;
4380 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4381 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4382 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4383 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004384 err_code |= ERR_ALERT | ERR_FATAL;
4385 goto out;
4386 }
4387 }
4388 else {
4389 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4390 file, linenum, args[0], args[1], ptr_arg);
4391 err_code |= ERR_ALERT | ERR_FATAL;
4392 goto out;
4393 }
4394 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004395 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004396 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 +02004397 err_code |= ERR_ALERT | ERR_FATAL;
4398 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004399 }
4400 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004401 else if (!strcmp(args[0], "tcp-check")) {
4402 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4403 err_code |= ERR_WARN;
4404
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004405 if (strcmp(args[1], "connect") == 0) {
4406 const char *ptr_arg;
4407 int cur_arg;
4408 struct tcpcheck_rule *tcpcheck;
4409 struct list *l;
4410
4411 /* check if first rule is also a 'connect' action */
4412 l = (struct list *)&curproxy->tcpcheck_rules;
4413 if (l->p != l->n) {
4414 tcpcheck = (struct tcpcheck_rule *)l->n;
4415 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4416 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4417 file, linenum);
4418 err_code |= ERR_ALERT | ERR_FATAL;
4419 goto out;
4420 }
4421 }
4422
4423 cur_arg = 2;
4424 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4425 tcpcheck->action = TCPCHK_ACT_CONNECT;
4426
4427 /* parsing each parameters to fill up the rule */
4428 while (*(ptr_arg = args[cur_arg])) {
4429 /* tcp port */
4430 if (strcmp(args[cur_arg], "port") == 0) {
4431 if ( (atol(args[cur_arg + 1]) > 65535) ||
4432 (atol(args[cur_arg + 1]) < 1) ){
4433 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4434 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4435 err_code |= ERR_ALERT | ERR_FATAL;
4436 goto out;
4437 }
4438 tcpcheck->port = atol(args[cur_arg + 1]);
4439 cur_arg += 2;
4440 }
4441 /* send proxy protocol */
4442 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4443 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4444 cur_arg++;
4445 }
4446#ifdef USE_OPENSSL
4447 else if (strcmp(args[cur_arg], "ssl") == 0) {
4448 curproxy->options |= PR_O_TCPCHK_SSL;
4449 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4450 cur_arg++;
4451 }
4452#endif /* USE_OPENSSL */
4453 else {
4454#ifdef USE_OPENSSL
4455 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4456#else /* USE_OPENSSL */
4457 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4458#endif /* USE_OPENSSL */
4459 file, linenum, args[0], args[1], args[cur_arg]);
4460 err_code |= ERR_ALERT | ERR_FATAL;
4461 goto out;
4462 }
4463
4464 }
4465
4466 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4467 }
4468 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004469 if (! *(args[2]) ) {
4470 /* SEND string expected */
4471 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4472 file, linenum, args[0], args[1], args[2]);
4473 err_code |= ERR_ALERT | ERR_FATAL;
4474 goto out;
4475 } else {
4476 struct tcpcheck_rule *tcpcheck;
4477
4478 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4479
4480 tcpcheck->action = TCPCHK_ACT_SEND;
4481 tcpcheck->string_len = strlen(args[2]);
4482 tcpcheck->string = strdup(args[2]);
4483 tcpcheck->expect_regex = NULL;
4484
4485 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4486 }
4487 }
4488 else if (strcmp(args[1], "send-binary") == 0) {
4489 if (! *(args[2]) ) {
4490 /* SEND binary string expected */
4491 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4492 file, linenum, args[0], args[1], args[2]);
4493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
4495 } else {
4496 struct tcpcheck_rule *tcpcheck;
4497 char *err = NULL;
4498
4499 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4500
4501 tcpcheck->action = TCPCHK_ACT_SEND;
4502 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4503 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4504 file, linenum, args[0], args[1], args[2], err);
4505 err_code |= ERR_ALERT | ERR_FATAL;
4506 goto out;
4507 }
4508 tcpcheck->expect_regex = NULL;
4509
4510 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4511 }
4512 }
4513 else if (strcmp(args[1], "expect") == 0) {
4514 const char *ptr_arg;
4515 int cur_arg;
4516 int inverse = 0;
4517
4518 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4519 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4520 err_code |= ERR_ALERT | ERR_FATAL;
4521 goto out;
4522 }
4523
4524 cur_arg = 2;
4525 /* consider exclamation marks, sole or at the beginning of a word */
4526 while (*(ptr_arg = args[cur_arg])) {
4527 while (*ptr_arg == '!') {
4528 inverse = !inverse;
4529 ptr_arg++;
4530 }
4531 if (*ptr_arg)
4532 break;
4533 cur_arg++;
4534 }
4535 /* now ptr_arg points to the beginning of a word past any possible
4536 * exclamation mark, and cur_arg is the argument which holds this word.
4537 */
4538 if (strcmp(ptr_arg, "binary") == 0) {
4539 if (!*(args[cur_arg + 1])) {
4540 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4541 file, linenum, args[0], args[1], ptr_arg);
4542 err_code |= ERR_ALERT | ERR_FATAL;
4543 goto out;
4544 }
4545 struct tcpcheck_rule *tcpcheck;
4546 char *err = NULL;
4547
4548 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4549
4550 tcpcheck->action = TCPCHK_ACT_EXPECT;
4551 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4552 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4553 file, linenum, args[0], args[1], args[2], err);
4554 err_code |= ERR_ALERT | ERR_FATAL;
4555 goto out;
4556 }
4557 tcpcheck->expect_regex = NULL;
4558 tcpcheck->inverse = inverse;
4559
4560 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4561 }
4562 else if (strcmp(ptr_arg, "string") == 0) {
4563 if (!*(args[cur_arg + 1])) {
4564 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4565 file, linenum, args[0], args[1], ptr_arg);
4566 err_code |= ERR_ALERT | ERR_FATAL;
4567 goto out;
4568 }
4569 struct tcpcheck_rule *tcpcheck;
4570
4571 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4572
4573 tcpcheck->action = TCPCHK_ACT_EXPECT;
4574 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4575 tcpcheck->string = strdup(args[cur_arg + 1]);
4576 tcpcheck->expect_regex = NULL;
4577 tcpcheck->inverse = inverse;
4578
4579 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4580 }
4581 else if (strcmp(ptr_arg, "rstring") == 0) {
4582 if (!*(args[cur_arg + 1])) {
4583 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4584 file, linenum, args[0], args[1], ptr_arg);
4585 err_code |= ERR_ALERT | ERR_FATAL;
4586 goto out;
4587 }
4588 struct tcpcheck_rule *tcpcheck;
4589
4590 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4591
4592 tcpcheck->action = TCPCHK_ACT_EXPECT;
4593 tcpcheck->string_len = 0;
4594 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004595 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4596 error = NULL;
4597 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4598 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4599 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4600 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004601 err_code |= ERR_ALERT | ERR_FATAL;
4602 goto out;
4603 }
4604 tcpcheck->inverse = inverse;
4605
4606 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4607 }
4608 else {
4609 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4610 file, linenum, args[0], args[1], ptr_arg);
4611 err_code |= ERR_ALERT | ERR_FATAL;
4612 goto out;
4613 }
4614 }
4615 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004616 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004617 err_code |= ERR_ALERT | ERR_FATAL;
4618 goto out;
4619 }
4620 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004621 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004622 if (curproxy == &defproxy) {
4623 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004624 err_code |= ERR_ALERT | ERR_FATAL;
4625 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004626 }
4627
Willy Tarreaub80c2302007-11-30 20:51:32 +01004628 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004629 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004630
4631 if (strcmp(args[1], "fail") == 0) {
4632 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004633 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004634 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4635 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004636 err_code |= ERR_ALERT | ERR_FATAL;
4637 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004638 }
4639
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004640 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4641 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4642 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004643 err_code |= ERR_ALERT | ERR_FATAL;
4644 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004645 }
4646 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4647 }
4648 else {
4649 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004650 err_code |= ERR_ALERT | ERR_FATAL;
4651 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004652 }
4653 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004654#ifdef TPROXY
4655 else if (!strcmp(args[0], "transparent")) {
4656 /* enable transparent proxy connections */
4657 curproxy->options |= PR_O_TRANSP;
4658 }
4659#endif
4660 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004661 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004662 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004663
Willy Tarreaubaaee002006-06-26 02:48:02 +02004664 if (*(args[1]) == 0) {
4665 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004666 err_code |= ERR_ALERT | ERR_FATAL;
4667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004668 }
4669 curproxy->maxconn = atol(args[1]);
4670 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004671 else if (!strcmp(args[0], "backlog")) { /* backlog */
4672 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004673 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004674
4675 if (*(args[1]) == 0) {
4676 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004677 err_code |= ERR_ALERT | ERR_FATAL;
4678 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004679 }
4680 curproxy->backlog = atol(args[1]);
4681 }
Willy Tarreau86034312006-12-29 00:10:33 +01004682 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004683 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004684 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004685
Willy Tarreau86034312006-12-29 00:10:33 +01004686 if (*(args[1]) == 0) {
4687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004688 err_code |= ERR_ALERT | ERR_FATAL;
4689 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004690 }
4691 curproxy->fullconn = atol(args[1]);
4692 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004693 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4694 if (*(args[1]) == 0) {
4695 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004696 err_code |= ERR_ALERT | ERR_FATAL;
4697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004698 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004699 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4700 if (err) {
4701 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4702 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004703 err_code |= ERR_ALERT | ERR_FATAL;
4704 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004705 }
4706 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004707 }
4708 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004709 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004710 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004711 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004712
Willy Tarreaubaaee002006-06-26 02:48:02 +02004713 if (curproxy == &defproxy) {
4714 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004715 err_code |= ERR_ALERT | ERR_FATAL;
4716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004717 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004718 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004719 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004720
Willy Tarreau902636f2013-03-10 19:44:48 +01004721 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004722 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004723 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004724 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004725 goto out;
4726 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004727
4728 proto = protocol_by_family(sk->ss_family);
4729 if (!proto || !proto->connect) {
4730 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4731 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004732 err_code |= ERR_ALERT | ERR_FATAL;
4733 goto out;
4734 }
4735
4736 if (port1 != port2) {
4737 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4738 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004739 err_code |= ERR_ALERT | ERR_FATAL;
4740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004741 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004742
4743 if (!port1) {
4744 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4745 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004746 err_code |= ERR_ALERT | ERR_FATAL;
4747 goto out;
4748 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004749
Willy Tarreaud5191e72010-02-09 20:50:45 +01004750 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004751 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004752 }
4753 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004754 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004755 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004756
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004757 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4758 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004759 err_code |= ERR_ALERT | ERR_FATAL;
4760 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004761 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004762 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004763 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004764 /**
4765 * The syntax for hash-type config element is
4766 * hash-type {map-based|consistent} [[<algo>] avalanche]
4767 *
4768 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4769 */
4770 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004771
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004772 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4773 err_code |= ERR_WARN;
4774
4775 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004776 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4777 }
4778 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004779 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4780 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004781 else if (strcmp(args[1], "avalanche") == 0) {
4782 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]);
4783 err_code |= ERR_ALERT | ERR_FATAL;
4784 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004785 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004786 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004787 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004788 err_code |= ERR_ALERT | ERR_FATAL;
4789 goto out;
4790 }
Bhaskar98634f02013-10-29 23:30:51 -04004791
4792 /* set the hash function to use */
4793 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004794 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004795 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004796
4797 /* if consistent with no argument, then avalanche modifier is also applied */
4798 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4799 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004800 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004801 /* set the hash function */
4802 if (!strcmp(args[2], "sdbm")) {
4803 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4804 }
4805 else if (!strcmp(args[2], "djb2")) {
4806 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004807 } else if (!strcmp(args[2], "wt6")) {
4808 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004809 }
4810 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004811 Alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2' or 'wt6' hash functions.\n", file, linenum, args[0]);
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004812 err_code |= ERR_ALERT | ERR_FATAL;
4813 goto out;
4814 }
4815
4816 /* set the hash modifier */
4817 if (!strcmp(args[3], "avalanche")) {
4818 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4819 }
4820 else if (*args[3]) {
4821 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4822 err_code |= ERR_ALERT | ERR_FATAL;
4823 goto out;
4824 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004825 }
William Lallemanda73203e2012-03-12 12:48:57 +01004826 }
William Lallemanda73203e2012-03-12 12:48:57 +01004827 else if (strcmp(args[0], "unique-id-format") == 0) {
4828 if (!*(args[1])) {
4829 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4830 err_code |= ERR_ALERT | ERR_FATAL;
4831 goto out;
4832 }
William Lallemand3203ff42012-11-11 17:30:56 +01004833 if (*(args[2])) {
4834 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4835 err_code |= ERR_ALERT | ERR_FATAL;
4836 goto out;
4837 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004838 free(curproxy->conf.uniqueid_format_string);
4839 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004840
Willy Tarreau62a61232013-04-12 18:13:46 +02004841 free(curproxy->conf.uif_file);
4842 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4843 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004844 }
William Lallemanda73203e2012-03-12 12:48:57 +01004845
4846 else if (strcmp(args[0], "unique-id-header") == 0) {
4847 if (!*(args[1])) {
4848 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4849 err_code |= ERR_ALERT | ERR_FATAL;
4850 goto out;
4851 }
4852 free(curproxy->header_unique_id);
4853 curproxy->header_unique_id = strdup(args[1]);
4854 }
4855
William Lallemand723b73a2012-02-08 16:37:49 +01004856 else if (strcmp(args[0], "log-format") == 0) {
4857 if (!*(args[1])) {
4858 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4859 err_code |= ERR_ALERT | ERR_FATAL;
4860 goto out;
4861 }
William Lallemand3203ff42012-11-11 17:30:56 +01004862 if (*(args[2])) {
4863 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4864 err_code |= ERR_ALERT | ERR_FATAL;
4865 goto out;
4866 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004867
Willy Tarreau62a61232013-04-12 18:13:46 +02004868 if (curproxy->conf.logformat_string != default_http_log_format &&
4869 curproxy->conf.logformat_string != default_tcp_log_format &&
4870 curproxy->conf.logformat_string != clf_http_log_format)
4871 free(curproxy->conf.logformat_string);
4872 curproxy->conf.logformat_string = strdup(args[1]);
4873
4874 free(curproxy->conf.lfs_file);
4875 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4876 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004877
4878 /* get a chance to improve log-format error reporting by
4879 * reporting the correct line-number when possible.
4880 */
4881 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4882 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4883 file, linenum, curproxy->id);
4884 err_code |= ERR_WARN;
4885 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004886 }
William Lallemand723b73a2012-02-08 16:37:49 +01004887
William Lallemand0f99e342011-10-12 17:50:54 +02004888 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4889 /* delete previous herited or defined syslog servers */
4890 struct logsrv *back;
4891
4892 if (*(args[1]) != 0) {
4893 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4894 err_code |= ERR_ALERT | ERR_FATAL;
4895 goto out;
4896 }
4897
William Lallemand723b73a2012-02-08 16:37:49 +01004898 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4899 LIST_DEL(&tmplogsrv->list);
4900 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004901 }
4902 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004903 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004904 struct logsrv *logsrv;
4905
Willy Tarreaubaaee002006-06-26 02:48:02 +02004906 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004907 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004908 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004909 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004910 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004911 LIST_INIT(&node->list);
4912 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4913 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004914 }
4915 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004916 struct sockaddr_storage *sk;
4917 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02004918 int arg = 0;
4919 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004920
4921 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004922
Willy Tarreau18324f52014-06-27 18:10:07 +02004923 /* just after the address, a length may be specified */
4924 if (strcmp(args[arg+2], "len") == 0) {
4925 len = atoi(args[arg+3]);
4926 if (len < 80 || len > 65535) {
4927 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4928 file, linenum, args[arg+3]);
4929 err_code |= ERR_ALERT | ERR_FATAL;
4930 goto out;
4931 }
4932 logsrv->maxlen = len;
4933
4934 /* skip these two args */
4935 arg += 2;
4936 }
4937 else
4938 logsrv->maxlen = MAX_SYSLOG_LEN;
4939
4940 if (logsrv->maxlen > global.max_syslog_len) {
4941 global.max_syslog_len = logsrv->maxlen;
4942 logline = realloc(logline, global.max_syslog_len + 1);
4943 }
4944
4945 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004946 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004947 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
4950
Willy Tarreaubaaee002006-06-26 02:48:02 +02004951 }
4952
William Lallemand0f99e342011-10-12 17:50:54 +02004953 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02004954 if (*(args[arg+3])) {
4955 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004956 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004957 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004958 err_code |= ERR_ALERT | ERR_FATAL;
4959 goto out;
4960
Willy Tarreaubaaee002006-06-26 02:48:02 +02004961 }
4962 }
4963
William Lallemand0f99e342011-10-12 17:50:54 +02004964 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02004965 if (*(args[arg+4])) {
4966 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004967 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004968 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004969 err_code |= ERR_ALERT | ERR_FATAL;
4970 goto out;
4971
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004972 }
4973 }
4974
Willy Tarreau902636f2013-03-10 19:44:48 +01004975 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004976 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004977 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004978 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004979 goto out;
4980 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004981
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004982 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004983
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004984 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004985 if (port1 != port2) {
4986 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4987 file, linenum, args[0], args[1]);
4988 err_code |= ERR_ALERT | ERR_FATAL;
4989 goto out;
4990 }
4991
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004992 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004993 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004994 }
William Lallemand0f99e342011-10-12 17:50:54 +02004995
4996 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997 }
4998 else {
4999 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5000 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005001 err_code |= ERR_ALERT | ERR_FATAL;
5002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005003 }
5004 }
5005 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005006 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005007 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005008 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005009 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005010
Willy Tarreau977b8e42006-12-29 14:19:17 +01005011 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005012 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005013
Willy Tarreaubaaee002006-06-26 02:48:02 +02005014 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005015 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5016 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005017 err_code |= ERR_ALERT | ERR_FATAL;
5018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005019 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005020
5021 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005022 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5023 free(curproxy->conn_src.iface_name);
5024 curproxy->conn_src.iface_name = NULL;
5025 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005026
Willy Tarreau902636f2013-03-10 19:44:48 +01005027 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005028 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005029 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005030 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005031 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005032 goto out;
5033 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005034
5035 proto = protocol_by_family(sk->ss_family);
5036 if (!proto || !proto->connect) {
5037 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005038 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005039 err_code |= ERR_ALERT | ERR_FATAL;
5040 goto out;
5041 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005042
5043 if (port1 != port2) {
5044 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5045 file, linenum, args[0], args[1]);
5046 err_code |= ERR_ALERT | ERR_FATAL;
5047 goto out;
5048 }
5049
Willy Tarreauef9a3602012-12-08 22:29:20 +01005050 curproxy->conn_src.source_addr = *sk;
5051 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005052
5053 cur_arg = 2;
5054 while (*(args[cur_arg])) {
5055 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005056#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5057#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005058 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005059 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5060 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005061 err_code |= ERR_ALERT | ERR_FATAL;
5062 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005063 }
5064#endif
5065 if (!*args[cur_arg + 1]) {
5066 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5067 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005068 err_code |= ERR_ALERT | ERR_FATAL;
5069 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005070 }
5071
5072 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005073 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5074 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005075 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005076 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5077 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005078 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5079 char *name, *end;
5080
5081 name = args[cur_arg+1] + 7;
5082 while (isspace(*name))
5083 name++;
5084
5085 end = name;
5086 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5087 end++;
5088
Willy Tarreauef9a3602012-12-08 22:29:20 +01005089 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5090 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5091 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5092 curproxy->conn_src.bind_hdr_len = end - name;
5093 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5094 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5095 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005096
5097 /* now look for an occurrence number */
5098 while (isspace(*end))
5099 end++;
5100 if (*end == ',') {
5101 end++;
5102 name = end;
5103 if (*end == '-')
5104 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005105 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005106 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005107 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005108 }
5109
Willy Tarreauef9a3602012-12-08 22:29:20 +01005110 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005111 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5112 " occurrences values smaller than %d.\n",
5113 file, linenum, MAX_HDR_HISTORY);
5114 err_code |= ERR_ALERT | ERR_FATAL;
5115 goto out;
5116 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005117 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005118 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005119
Willy Tarreau902636f2013-03-10 19:44:48 +01005120 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005121 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005122 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005123 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005124 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005125 goto out;
5126 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005127
5128 proto = protocol_by_family(sk->ss_family);
5129 if (!proto || !proto->connect) {
5130 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5131 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005132 err_code |= ERR_ALERT | ERR_FATAL;
5133 goto out;
5134 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005135
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005136 if (port1 != port2) {
5137 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5138 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005139 err_code |= ERR_ALERT | ERR_FATAL;
5140 goto out;
5141 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005142 curproxy->conn_src.tproxy_addr = *sk;
5143 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005144 }
5145 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005146#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005147 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005148#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005149#else /* no TPROXY support */
5150 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005151 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005152 err_code |= ERR_ALERT | ERR_FATAL;
5153 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005154#endif
5155 cur_arg += 2;
5156 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005157 }
5158
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005159 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5160#ifdef SO_BINDTODEVICE
5161 if (!*args[cur_arg + 1]) {
5162 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5163 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005164 err_code |= ERR_ALERT | ERR_FATAL;
5165 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005166 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005167 free(curproxy->conn_src.iface_name);
5168 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5169 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005170 global.last_checks |= LSTCHK_NETADM;
5171#else
5172 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5173 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005174 err_code |= ERR_ALERT | ERR_FATAL;
5175 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005176#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005177 cur_arg += 2;
5178 continue;
5179 }
5180 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005181 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005182 err_code |= ERR_ALERT | ERR_FATAL;
5183 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005184 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005185 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005186 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5187 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5188 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005189 err_code |= ERR_ALERT | ERR_FATAL;
5190 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005192 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005193 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005194 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5195 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005196 err_code |= ERR_ALERT | ERR_FATAL;
5197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005198 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005199
5200 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005201 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005202 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005203 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005205 }
5206 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005207 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005208 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005209 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005210 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005211 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005212 }
5213 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005214 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005215 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005216 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005217 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005218 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005219 }
5220 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005221 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005222 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005223 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005224 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005225 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005226 }
5227 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005228 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005229 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005230 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005231 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005233 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005234 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005235 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005236 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005237 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005238 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005239 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005240 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005241 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005242 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005243 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005244 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005245 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005246 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005247
5248 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5249 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 +01005250 }
5251 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005252 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005253 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005254 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005255 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005256 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005257
5258 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5259 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 +01005260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005261 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005262 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005263 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5264 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005265 err_code |= ERR_ALERT | ERR_FATAL;
5266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005267 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005268
5269 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005270 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005271 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005272 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005274 }
5275 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005276 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005277 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005278 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005279 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005281 }
5282 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005283 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005284 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005285 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005286 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005288 }
5289 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005290 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005291 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005292 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005293 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005295 }
5296 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005297 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005298 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005299 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005300 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005302 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005303 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005304 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005305 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005306 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005307 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005308 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005309 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005311 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005312
Willy Tarreaubaaee002006-06-26 02:48:02 +02005313 if (curproxy == &defproxy) {
5314 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005315 err_code |= ERR_ALERT | ERR_FATAL;
5316 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005317 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005318 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005319 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005320
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321 if (*(args[1]) == 0) {
5322 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005323 err_code |= ERR_ALERT | ERR_FATAL;
5324 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005325 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005326
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005327 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005328 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5329 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5330 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005331 err_code |= ERR_ALERT | ERR_FATAL;
5332 goto out;
5333 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005334 err_code |= warnif_cond_conflicts(cond,
5335 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5336 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005337 }
5338 else if (*args[2]) {
5339 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5340 file, linenum, args[0], args[2]);
5341 err_code |= ERR_ALERT | ERR_FATAL;
5342 goto out;
5343 }
5344
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005345 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005346 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005347 wl->s = strdup(args[1]);
5348 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005349 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005350 }
5351 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005352 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005353 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5354 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005355 err_code |= ERR_ALERT | ERR_FATAL;
5356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005357 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005358
Willy Tarreauade5ec42010-01-28 19:33:49 +01005359 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005360 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005361 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005362 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005364 }
5365 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005366 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005367 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005368 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005369 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005371 }
5372 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005373 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005374 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005375 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005376 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005378 }
5379 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005380 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005381 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5382 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005383 err_code |= ERR_ALERT | ERR_FATAL;
5384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005385 }
5386
Willy Tarreauade5ec42010-01-28 19:33:49 +01005387 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005388 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005389 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005390 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005392 }
5393 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005394 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005395 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005396 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005397 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005399 }
5400 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005401 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005402 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005403 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005404 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005406 }
5407 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005408 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005409
Willy Tarreaubaaee002006-06-26 02:48:02 +02005410 if (curproxy == &defproxy) {
5411 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005412 err_code |= ERR_ALERT | ERR_FATAL;
5413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005414 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005415 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005416 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005417
Willy Tarreaubaaee002006-06-26 02:48:02 +02005418 if (*(args[1]) == 0) {
5419 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005420 err_code |= ERR_ALERT | ERR_FATAL;
5421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005422 }
5423
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005424 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005425 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5426 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5427 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005428 err_code |= ERR_ALERT | ERR_FATAL;
5429 goto out;
5430 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005431 err_code |= warnif_cond_conflicts(cond,
5432 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5433 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005434 }
5435 else if (*args[2]) {
5436 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5437 file, linenum, args[0], args[2]);
5438 err_code |= ERR_ALERT | ERR_FATAL;
5439 goto out;
5440 }
5441
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005442 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005443 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005444 wl->s = strdup(args[1]);
5445 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005446 }
5447 else if (!strcmp(args[0], "errorloc") ||
5448 !strcmp(args[0], "errorloc302") ||
5449 !strcmp(args[0], "errorloc303")) { /* error location */
5450 int errnum, errlen;
5451 char *err;
5452
Willy Tarreau977b8e42006-12-29 14:19:17 +01005453 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005454 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005455
Willy Tarreaubaaee002006-06-26 02:48:02 +02005456 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005457 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005458 err_code |= ERR_ALERT | ERR_FATAL;
5459 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005460 }
5461
5462 errnum = atol(args[1]);
5463 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005464 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5465 err = malloc(errlen);
5466 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005467 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005468 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5469 err = malloc(errlen);
5470 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005471 }
5472
Willy Tarreau0f772532006-12-23 20:51:41 +01005473 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5474 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005475 chunk_destroy(&curproxy->errmsg[rc]);
5476 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005477 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005478 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005479 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005480
5481 if (rc >= HTTP_ERR_SIZE) {
5482 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5483 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005484 free(err);
5485 }
5486 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005487 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5488 int errnum, errlen, fd;
5489 char *err;
5490 struct stat stat;
5491
5492 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005493 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005494
5495 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005496 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005497 err_code |= ERR_ALERT | ERR_FATAL;
5498 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005499 }
5500
5501 fd = open(args[2], O_RDONLY);
5502 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5503 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5504 file, linenum, args[2], args[1]);
5505 if (fd >= 0)
5506 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005507 err_code |= ERR_ALERT | ERR_FATAL;
5508 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005509 }
5510
Willy Tarreau27a674e2009-08-17 07:23:33 +02005511 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005512 errlen = stat.st_size;
5513 } else {
5514 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005515 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005516 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005517 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005518 }
5519
5520 err = malloc(errlen); /* malloc() must succeed during parsing */
5521 errnum = read(fd, err, errlen);
5522 if (errnum != errlen) {
5523 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5524 file, linenum, args[2], args[1]);
5525 close(fd);
5526 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005527 err_code |= ERR_ALERT | ERR_FATAL;
5528 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005529 }
5530 close(fd);
5531
5532 errnum = atol(args[1]);
5533 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5534 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005535 chunk_destroy(&curproxy->errmsg[rc]);
5536 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005537 break;
5538 }
5539 }
5540
5541 if (rc >= HTTP_ERR_SIZE) {
5542 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5543 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005544 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005545 free(err);
5546 }
5547 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005548 else if (!strcmp(args[0], "compression")) {
5549 struct comp *comp;
5550 if (curproxy->comp == NULL) {
5551 comp = calloc(1, sizeof(struct comp));
5552 curproxy->comp = comp;
5553 } else {
5554 comp = curproxy->comp;
5555 }
5556
5557 if (!strcmp(args[1], "algo")) {
5558 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005559 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005560
William Lallemand82fe75c2012-10-23 10:25:10 +02005561 cur_arg = 2;
5562 if (!*args[cur_arg]) {
5563 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5564 file, linenum, args[0]);
5565 err_code |= ERR_ALERT | ERR_FATAL;
5566 goto out;
5567 }
5568 while (*(args[cur_arg])) {
5569 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5570 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5571 file, linenum, args[0], args[cur_arg]);
5572 err_code |= ERR_ALERT | ERR_FATAL;
5573 goto out;
5574 }
William Lallemand552df672012-11-07 13:21:47 +01005575 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5576 curproxy->comp->algos->end(&ctx);
5577 } else {
5578 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5579 file, linenum, args[0], args[cur_arg]);
5580 err_code |= ERR_ALERT | ERR_FATAL;
5581 goto out;
5582 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005583 cur_arg ++;
5584 continue;
5585 }
5586 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005587 else if (!strcmp(args[1], "offload")) {
5588 comp->offload = 1;
5589 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005590 else if (!strcmp(args[1], "type")) {
5591 int cur_arg;
5592 cur_arg = 2;
5593 if (!*args[cur_arg]) {
5594 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5595 file, linenum, args[0]);
5596 err_code |= ERR_ALERT | ERR_FATAL;
5597 goto out;
5598 }
5599 while (*(args[cur_arg])) {
5600 comp_append_type(comp, args[cur_arg]);
5601 cur_arg ++;
5602 continue;
5603 }
5604 }
5605 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005606 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005607 file, linenum, args[0]);
5608 err_code |= ERR_ALERT | ERR_FATAL;
5609 goto out;
5610 }
5611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005612 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005613 struct cfg_kw_list *kwl;
5614 int index;
5615
5616 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5617 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5618 if (kwl->kw[index].section != CFG_LISTEN)
5619 continue;
5620 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5621 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005622 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005623 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005624 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005625 err_code |= ERR_ALERT | ERR_FATAL;
5626 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005627 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005628 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005629 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005630 err_code |= ERR_WARN;
5631 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005632 }
Willy Tarreau93893792009-07-23 13:19:11 +02005633 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005634 }
5635 }
5636 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005637
Willy Tarreau6daf3432008-01-22 16:44:08 +01005638 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005639 err_code |= ERR_ALERT | ERR_FATAL;
5640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005641 }
Willy Tarreau93893792009-07-23 13:19:11 +02005642 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005643 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005644 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005645}
5646
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005647int
5648cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5649{
5650
5651 int err_code = 0;
5652 const char *err;
5653
5654 if (!strcmp(args[0], "userlist")) { /* new userlist */
5655 struct userlist *newul;
5656
5657 if (!*args[1]) {
5658 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5659 file, linenum, args[0]);
5660 err_code |= ERR_ALERT | ERR_FATAL;
5661 goto out;
5662 }
5663
5664 err = invalid_char(args[1]);
5665 if (err) {
5666 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5667 file, linenum, *err, args[0], args[1]);
5668 err_code |= ERR_ALERT | ERR_FATAL;
5669 goto out;
5670 }
5671
5672 for (newul = userlist; newul; newul = newul->next)
5673 if (!strcmp(newul->name, args[1])) {
5674 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5675 file, linenum, args[1]);
5676 err_code |= ERR_WARN;
5677 goto out;
5678 }
5679
5680 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5681 if (!newul) {
5682 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5683 err_code |= ERR_ALERT | ERR_ABORT;
5684 goto out;
5685 }
5686
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005687 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005688 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005689 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5690 err_code |= ERR_ALERT | ERR_ABORT;
5691 goto out;
5692 }
5693
5694 newul->next = userlist;
5695 userlist = newul;
5696
5697 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005698 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005699 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005700 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005701
5702 if (!*args[1]) {
5703 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5704 file, linenum, args[0]);
5705 err_code |= ERR_ALERT | ERR_FATAL;
5706 goto out;
5707 }
5708
5709 err = invalid_char(args[1]);
5710 if (err) {
5711 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5712 file, linenum, *err, args[0], args[1]);
5713 err_code |= ERR_ALERT | ERR_FATAL;
5714 goto out;
5715 }
5716
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005717 for (ag = userlist->groups; ag; ag = ag->next)
5718 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005719 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5720 file, linenum, args[1], userlist->name);
5721 err_code |= ERR_ALERT;
5722 goto out;
5723 }
5724
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005725 ag = calloc(1, sizeof(*ag));
5726 if (!ag) {
5727 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5728 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005729 goto out;
5730 }
5731
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005732 ag->name = strdup(args[1]);
5733 if (!ag) {
5734 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5735 err_code |= ERR_ALERT | ERR_ABORT;
5736 goto out;
5737 }
5738
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005739 cur_arg = 2;
5740
5741 while (*args[cur_arg]) {
5742 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005743 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005744 cur_arg += 2;
5745 continue;
5746 } else {
5747 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5748 file, linenum, args[0]);
5749 err_code |= ERR_ALERT | ERR_FATAL;
5750 goto out;
5751 }
5752 }
5753
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005754 ag->next = userlist->groups;
5755 userlist->groups = ag;
5756
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005757 } else if (!strcmp(args[0], "user")) { /* new user */
5758 struct auth_users *newuser;
5759 int cur_arg;
5760
5761 if (!*args[1]) {
5762 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5763 file, linenum, args[0]);
5764 err_code |= ERR_ALERT | ERR_FATAL;
5765 goto out;
5766 }
5767
5768 for (newuser = userlist->users; newuser; newuser = newuser->next)
5769 if (!strcmp(newuser->user, args[1])) {
5770 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5771 file, linenum, args[1], userlist->name);
5772 err_code |= ERR_ALERT;
5773 goto out;
5774 }
5775
5776 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5777 if (!newuser) {
5778 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5779 err_code |= ERR_ALERT | ERR_ABORT;
5780 goto out;
5781 }
5782
5783 newuser->user = strdup(args[1]);
5784
5785 newuser->next = userlist->users;
5786 userlist->users = newuser;
5787
5788 cur_arg = 2;
5789
5790 while (*args[cur_arg]) {
5791 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02005792#ifdef CONFIG_HAP_CRYPT
5793 if (!crypt("", args[cur_arg + 1])) {
5794 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
5795 file, linenum, newuser->user);
5796 err_code |= ERR_ALERT | ERR_FATAL;
5797 goto out;
5798 }
5799#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005800 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5801 file, linenum);
5802 err_code |= ERR_ALERT;
5803#endif
5804 newuser->pass = strdup(args[cur_arg + 1]);
5805 cur_arg += 2;
5806 continue;
5807 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5808 newuser->pass = strdup(args[cur_arg + 1]);
5809 newuser->flags |= AU_O_INSECURE;
5810 cur_arg += 2;
5811 continue;
5812 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005813 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005814 cur_arg += 2;
5815 continue;
5816 } else {
5817 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5818 file, linenum, args[0]);
5819 err_code |= ERR_ALERT | ERR_FATAL;
5820 goto out;
5821 }
5822 }
5823 } else {
5824 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5825 err_code |= ERR_ALERT | ERR_FATAL;
5826 }
5827
5828out:
5829 return err_code;
5830}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005831
5832/*
5833 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005834 * Returns the error code, 0 if OK, or any combination of :
5835 * - ERR_ABORT: must abort ASAP
5836 * - ERR_FATAL: we can continue parsing but not start the service
5837 * - ERR_WARN: a warning has been emitted
5838 * - ERR_ALERT: an alert has been emitted
5839 * Only the two first ones can stop processing, the two others are just
5840 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005841 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005842int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005843{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005844 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005845 FILE *f;
5846 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005847 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005848 struct cfg_section *cs = NULL;
5849 struct cfg_section *ics;
5850
5851 /* Register internal sections */
5852 if (!cfg_register_section("listen", cfg_parse_listen) ||
5853 !cfg_register_section("frontend", cfg_parse_listen) ||
5854 !cfg_register_section("backend", cfg_parse_listen) ||
5855 !cfg_register_section("ruleset", cfg_parse_listen) ||
5856 !cfg_register_section("defaults", cfg_parse_listen) ||
5857 !cfg_register_section("global", cfg_parse_global) ||
5858 !cfg_register_section("userlist", cfg_parse_users) ||
5859 !cfg_register_section("peers", cfg_parse_peers))
5860 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005861
Willy Tarreaubaaee002006-06-26 02:48:02 +02005862 if ((f=fopen(file,"r")) == NULL)
5863 return -1;
5864
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005865 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005866 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005867 char *end;
5868 char *args[MAX_LINE_ARGS + 1];
5869 char *line = thisline;
5870
Willy Tarreaubaaee002006-06-26 02:48:02 +02005871 linenum++;
5872
5873 end = line + strlen(line);
5874
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005875 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5876 /* Check if we reached the limit and the last char is not \n.
5877 * Watch out for the last line without the terminating '\n'!
5878 */
5879 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005880 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005881 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005882 }
5883
Willy Tarreaubaaee002006-06-26 02:48:02 +02005884 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005885 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005886 line++;
5887
5888 arg = 0;
5889 args[arg] = line;
5890
5891 while (*line && arg < MAX_LINE_ARGS) {
5892 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5893 * C equivalent value. Other combinations left unchanged (eg: \1).
5894 */
5895 if (*line == '\\') {
5896 int skip = 0;
5897 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5898 *line = line[1];
5899 skip = 1;
5900 }
5901 else if (line[1] == 'r') {
5902 *line = '\r';
5903 skip = 1;
5904 }
5905 else if (line[1] == 'n') {
5906 *line = '\n';
5907 skip = 1;
5908 }
5909 else if (line[1] == 't') {
5910 *line = '\t';
5911 skip = 1;
5912 }
5913 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005914 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005915 unsigned char hex1, hex2;
5916 hex1 = toupper(line[2]) - '0';
5917 hex2 = toupper(line[3]) - '0';
5918 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5919 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5920 *line = (hex1<<4) + hex2;
5921 skip = 3;
5922 }
5923 else {
5924 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005925 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005926 }
5927 }
5928 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005929 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005930 end -= skip;
5931 }
5932 line++;
5933 }
5934 else if (*line == '#' || *line == '\n' || *line == '\r') {
5935 /* end of string, end of loop */
5936 *line = 0;
5937 break;
5938 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005939 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005940 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005941 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005942 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005943 line++;
5944 args[++arg] = line;
5945 }
5946 else {
5947 line++;
5948 }
5949 }
5950
5951 /* empty line */
5952 if (!**args)
5953 continue;
5954
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005955 if (*line) {
5956 /* we had to stop due to too many args.
5957 * Let's terminate the string, print the offending part then cut the
5958 * last arg.
5959 */
5960 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5961 line++;
5962 *line = '\0';
5963
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005964 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005965 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005966 err_code |= ERR_ALERT | ERR_FATAL;
5967 args[arg] = line;
5968 }
5969
Willy Tarreau540abe42007-05-02 20:50:16 +02005970 /* zero out remaining args and ensure that at least one entry
5971 * is zeroed out.
5972 */
5973 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005974 args[arg] = line;
5975 }
5976
Willy Tarreau3842f002009-06-14 11:39:52 +02005977 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005978 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005979 char *tmp;
5980
Willy Tarreau3842f002009-06-14 11:39:52 +02005981 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005982 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005983 for (arg=0; *args[arg+1]; arg++)
5984 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005985 *tmp = '\0'; // fix the next arg to \0
5986 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005987 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005988 else if (!strcmp(args[0], "default")) {
5989 kwm = KWM_DEF;
5990 for (arg=0; *args[arg+1]; arg++)
5991 args[arg] = args[arg+1]; // shift args after inversion
5992 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005993
William Lallemand0f99e342011-10-12 17:50:54 +02005994 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5995 strcmp(args[0], "log") != 0) {
5996 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005997 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005998 }
5999
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006000 /* detect section start */
6001 list_for_each_entry(ics, &sections, list) {
6002 if (strcmp(args[0], ics->section_name) == 0) {
6003 cursection = ics->section_name;
6004 cs = ics;
6005 break;
6006 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006007 }
6008
Willy Tarreaubaaee002006-06-26 02:48:02 +02006009 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006010 if (cs)
6011 err_code |= cs->section_parser(file, linenum, args, kwm);
6012 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006013 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006014 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006015 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006016
6017 if (err_code & ERR_ABORT)
6018 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006019 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006020 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006021 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006022 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006023}
6024
Willy Tarreau64ab6072014-09-16 12:17:36 +02006025/* This function propagates processes from frontend <from> to backend <to> so
6026 * that it is always guaranteed that a backend pointed to by a frontend is
6027 * bound to all of its processes. After that, if the target is a "listen"
6028 * instance, the function recursively descends the target's own targets along
6029 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6030 * checked first to ensure that <to> is already bound to all processes of
6031 * <from>, there is no risk of looping and we ensure to follow the shortest
6032 * path to the destination.
6033 *
6034 * It is possible to set <to> to NULL for the first call so that the function
6035 * takes care of visiting the initial frontend in <from>.
6036 *
6037 * It is important to note that the function relies on the fact that all names
6038 * have already been resolved.
6039 */
6040void propagate_processes(struct proxy *from, struct proxy *to)
6041{
6042 struct switching_rule *rule;
6043 struct hdr_exp *exp;
6044
6045 if (to) {
6046 /* check whether we need to go down */
6047 if (from->bind_proc &&
6048 (from->bind_proc & to->bind_proc) == from->bind_proc)
6049 return;
6050
6051 if (!from->bind_proc && !to->bind_proc)
6052 return;
6053
6054 to->bind_proc = from->bind_proc ?
6055 (to->bind_proc | from->bind_proc) : 0;
6056
6057 /* now propagate down */
6058 from = to;
6059 }
6060
6061 if (!from->cap & PR_CAP_FE)
6062 return;
6063
6064 /* default_backend */
6065 if (from->defbe.be)
6066 propagate_processes(from, from->defbe.be);
6067
6068 /* use_backend */
6069 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006070 if (rule->dynamic)
6071 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006072 to = rule->be.backend;
6073 propagate_processes(from, to);
6074 }
6075
6076 /* reqsetbe */
6077 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6078 if (exp->action != ACT_SETBE)
6079 continue;
6080 to = (struct proxy *)exp->replace;
6081 propagate_processes(from, to);
6082 }
6083}
6084
Willy Tarreaubb925012009-07-23 13:36:36 +02006085/*
6086 * Returns the error code, 0 if OK, or any combination of :
6087 * - ERR_ABORT: must abort ASAP
6088 * - ERR_FATAL: we can continue parsing but not start the service
6089 * - ERR_WARN: a warning has been emitted
6090 * - ERR_ALERT: an alert has been emitted
6091 * Only the two first ones can stop processing, the two others are just
6092 * indicators.
6093 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006094int check_config_validity()
6095{
6096 int cfgerr = 0;
6097 struct proxy *curproxy = NULL;
6098 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006099 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006100 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006101 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006102
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006103 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006104 /*
6105 * Now, check for the integrity of all that we have collected.
6106 */
6107
6108 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006109 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006110
Willy Tarreau193b8c62012-11-22 00:17:38 +01006111 if (!global.tune.max_http_hdr)
6112 global.tune.max_http_hdr = MAX_HTTP_HDR;
6113
6114 if (!global.tune.cookie_len)
6115 global.tune.cookie_len = CAPTURE_LEN;
6116
6117 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6118
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006119 /* Post initialisation of the users and groups lists. */
6120 err_code = userlist_postinit();
6121 if (err_code != ERR_NONE)
6122 goto out;
6123
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006124 /* first, we will invert the proxy list order */
6125 curproxy = NULL;
6126 while (proxy) {
6127 struct proxy *next;
6128
6129 next = proxy->next;
6130 proxy->next = curproxy;
6131 curproxy = proxy;
6132 if (!next)
6133 break;
6134 proxy = next;
6135 }
6136
Willy Tarreau419ead82014-09-16 13:41:21 +02006137 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006138 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006139 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006140 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006141 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006142 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006143 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006144 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006145
Willy Tarreau050536d2012-10-04 08:47:34 +02006146 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006147 /* proxy ID not set, use automatic numbering with first
6148 * spare entry starting with next_pxid.
6149 */
6150 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6151 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6152 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006153 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006154 next_pxid++;
6155
Willy Tarreau55ea7572007-06-17 19:56:27 +02006156
Willy Tarreaubaaee002006-06-26 02:48:02 +02006157 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006158 /* ensure we don't keep listeners uselessly bound */
6159 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006160 continue;
6161 }
6162
Willy Tarreau102df612014-05-07 23:56:38 +02006163 /* Check multi-process mode compatibility for the current proxy */
6164
6165 if (curproxy->bind_proc) {
6166 /* an explicit bind-process was specified, let's check how many
6167 * processes remain.
6168 */
6169 nbproc = popcount(curproxy->bind_proc);
6170
6171 curproxy->bind_proc &= nbits(global.nbproc);
6172 if (!curproxy->bind_proc && nbproc == 1) {
6173 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);
6174 curproxy->bind_proc = 1;
6175 }
6176 else if (!curproxy->bind_proc && nbproc > 1) {
6177 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);
6178 curproxy->bind_proc = 0;
6179 }
6180 }
6181
Willy Tarreau3d209582014-05-09 17:06:11 +02006182 /* check and reduce the bind-proc of each listener */
6183 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6184 unsigned long mask;
6185
6186 if (!bind_conf->bind_proc)
6187 continue;
6188
6189 mask = nbits(global.nbproc);
6190 if (curproxy->bind_proc)
6191 mask &= curproxy->bind_proc;
6192 /* mask cannot be null here thanks to the previous checks */
6193
6194 nbproc = popcount(bind_conf->bind_proc);
6195 bind_conf->bind_proc &= mask;
6196
6197 if (!bind_conf->bind_proc && nbproc == 1) {
6198 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",
6199 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6200 bind_conf->bind_proc = mask & ~(mask - 1);
6201 }
6202 else if (!bind_conf->bind_proc && nbproc > 1) {
6203 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",
6204 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6205 bind_conf->bind_proc = 0;
6206 }
6207 }
6208
Willy Tarreau102df612014-05-07 23:56:38 +02006209 if (global.nbproc > 1 && curproxy->table.peers.name) {
6210 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6211 curproxy->id);
6212 cfgerr++;
6213 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006214
Willy Tarreauff01a212009-03-15 13:46:16 +01006215 switch (curproxy->mode) {
6216 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006217 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006218 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006219 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6220 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006221 cfgerr++;
6222 }
6223
6224 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006225 Warning("config : servers will be ignored for %s '%s'.\n",
6226 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006227 break;
6228
6229 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006230 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006231 break;
6232
6233 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006234 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006235 break;
6236 }
6237
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006238 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006239 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006240 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006241 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6242 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006243 cfgerr++;
6244 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006245#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006246 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006247 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6248 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006249 cfgerr++;
6250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006251#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006252 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006253 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6254 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006255 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006256 }
6257 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006258 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006259 /* If no LB algo is set in a backend, and we're not in
6260 * transparent mode, dispatch mode nor proxy mode, we
6261 * want to use balance roundrobin by default.
6262 */
6263 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6264 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006265 }
6266 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006267
Willy Tarreau1620ec32011-08-06 17:05:02 +02006268 if (curproxy->options & PR_O_DISPATCH)
6269 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6270 else if (curproxy->options & PR_O_HTTP_PROXY)
6271 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6272 else if (curproxy->options & PR_O_TRANSP)
6273 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006274
Willy Tarreau1620ec32011-08-06 17:05:02 +02006275 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6276 if (curproxy->options & PR_O_DISABLE404) {
6277 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6278 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6279 err_code |= ERR_WARN;
6280 curproxy->options &= ~PR_O_DISABLE404;
6281 }
6282 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6283 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6284 "send-state", proxy_type_str(curproxy), curproxy->id);
6285 err_code |= ERR_WARN;
6286 curproxy->options &= ~PR_O2_CHK_SNDST;
6287 }
Willy Tarreauef781042010-01-27 11:53:01 +01006288 }
6289
Simon Horman98637e52014-06-20 12:30:16 +09006290 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6291 if (!global.external_check) {
6292 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6293 curproxy->id, "option external-check");
6294 cfgerr++;
6295 }
6296 if (!curproxy->check_command) {
6297 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6298 curproxy->id, "option external-check");
6299 cfgerr++;
6300 }
6301 }
6302
6303 if (curproxy->check_command) {
6304 int clear = 0;
6305 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6306 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6307 "external-check command", proxy_type_str(curproxy), curproxy->id);
6308 err_code |= ERR_WARN;
6309 clear = 1;
6310 }
6311 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6312 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6313 curproxy->id, "external-check command");
6314 cfgerr++;
6315 }
6316 if (clear) {
6317 free(curproxy->check_command);
6318 curproxy->check_command = NULL;
6319 }
6320 }
6321
6322 if (curproxy->check_path) {
6323 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6324 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6325 "external-check path", proxy_type_str(curproxy), curproxy->id);
6326 err_code |= ERR_WARN;
6327 free(curproxy->check_path);
6328 curproxy->check_path = NULL;
6329 }
6330 }
6331
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006332 /* if a default backend was specified, let's find it */
6333 if (curproxy->defbe.name) {
6334 struct proxy *target;
6335
Alex Williams96532db2009-11-01 21:27:13 -05006336 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006337 if (!target) {
6338 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6339 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006340 cfgerr++;
6341 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006342 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6343 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006344 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006345 } else {
6346 free(curproxy->defbe.name);
6347 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006348
6349 /* Emit a warning if this proxy also has some servers */
6350 if (curproxy->srv) {
6351 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6352 curproxy->id);
6353 err_code |= ERR_WARN;
6354 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006355 }
6356 }
6357
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006358 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006359 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6360 /* map jump target for ACT_SETBE in req_rep chain */
6361 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006362 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006363 struct proxy *target;
6364
Willy Tarreaua496b602006-12-17 23:15:24 +01006365 if (exp->action != ACT_SETBE)
6366 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006367
Alex Williams96532db2009-11-01 21:27:13 -05006368 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006369 if (!target) {
6370 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6371 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006372 cfgerr++;
6373 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006374 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6375 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006376 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006377 } else {
6378 free((void *)exp->replace);
6379 exp->replace = (const char *)target;
6380 }
6381 }
6382 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006383
6384 /* find the target proxy for 'use_backend' rules */
6385 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006386 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006387 struct logformat_node *node;
6388 char *pxname;
6389
6390 /* Try to parse the string as a log format expression. If the result
6391 * of the parsing is only one entry containing a simple string, then
6392 * it's a standard string corresponding to a static rule, thus the
6393 * parsing is cancelled and be.name is restored to be resolved.
6394 */
6395 pxname = rule->be.name;
6396 LIST_INIT(&rule->be.expr);
6397 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6398 curproxy->conf.args.file, curproxy->conf.args.line);
6399 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6400
6401 if (!LIST_ISEMPTY(&rule->be.expr)) {
6402 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6403 rule->dynamic = 1;
6404 free(pxname);
6405 continue;
6406 }
6407 /* simple string: free the expression and fall back to static rule */
6408 free(node->arg);
6409 free(node);
6410 }
6411
6412 rule->dynamic = 0;
6413 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006414
Alex Williams96532db2009-11-01 21:27:13 -05006415 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006416
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006417 if (!target) {
6418 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6419 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006420 cfgerr++;
6421 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006422 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6423 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006424 cfgerr++;
6425 } else {
6426 free((void *)rule->be.name);
6427 rule->be.backend = target;
6428 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006429 }
6430
Willy Tarreau64ab6072014-09-16 12:17:36 +02006431 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006432 list_for_each_entry(srule, &curproxy->server_rules, list) {
6433 struct server *target = findserver(curproxy, srule->srv.name);
6434
6435 if (!target) {
6436 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6437 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6438 cfgerr++;
6439 continue;
6440 }
6441 free((void *)srule->srv.name);
6442 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006443 }
6444
Emeric Brunb982a3d2010-01-04 15:45:53 +01006445 /* find the target table for 'stick' rules */
6446 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6447 struct proxy *target;
6448
Emeric Brun1d33b292010-01-04 15:47:17 +01006449 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6450 if (mrule->flags & STK_IS_STORE)
6451 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6452
Emeric Brunb982a3d2010-01-04 15:45:53 +01006453 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006454 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006455 else
6456 target = curproxy;
6457
6458 if (!target) {
6459 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6460 curproxy->id, mrule->table.name);
6461 cfgerr++;
6462 }
6463 else if (target->table.size == 0) {
6464 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6465 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6466 cfgerr++;
6467 }
Willy Tarreau12785782012-04-27 21:37:17 +02006468 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6469 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006470 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6471 cfgerr++;
6472 }
6473 else {
6474 free((void *)mrule->table.name);
6475 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006476 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006477 }
6478 }
6479
6480 /* find the target table for 'store response' rules */
6481 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6482 struct proxy *target;
6483
Emeric Brun1d33b292010-01-04 15:47:17 +01006484 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6485
Emeric Brunb982a3d2010-01-04 15:45:53 +01006486 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006487 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006488 else
6489 target = curproxy;
6490
6491 if (!target) {
6492 Alert("Proxy '%s': unable to find store table '%s'.\n",
6493 curproxy->id, mrule->table.name);
6494 cfgerr++;
6495 }
6496 else if (target->table.size == 0) {
6497 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6498 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6499 cfgerr++;
6500 }
Willy Tarreau12785782012-04-27 21:37:17 +02006501 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6502 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006503 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6504 cfgerr++;
6505 }
6506 else {
6507 free((void *)mrule->table.name);
6508 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006509 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006510 }
6511 }
6512
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006513 /* find the target table for 'tcp-request' layer 4 rules */
6514 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6515 struct proxy *target;
6516
Willy Tarreaub4c84932013-07-23 19:15:30 +02006517 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006518 continue;
6519
6520 if (trule->act_prm.trk_ctr.table.n)
6521 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6522 else
6523 target = curproxy;
6524
6525 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006526 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6527 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006528 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006529 cfgerr++;
6530 }
6531 else if (target->table.size == 0) {
6532 Alert("Proxy '%s': table '%s' used but not configured.\n",
6533 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6534 cfgerr++;
6535 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006536 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6537 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6538 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 +01006539 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006540 cfgerr++;
6541 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006542 else {
6543 free(trule->act_prm.trk_ctr.table.n);
6544 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006545 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006546 * to pass a list of counters to track and allocate them right here using
6547 * stktable_alloc_data_type().
6548 */
6549 }
6550 }
6551
Willy Tarreaud1f96522010-08-03 19:34:32 +02006552 /* find the target table for 'tcp-request' layer 6 rules */
6553 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6554 struct proxy *target;
6555
Willy Tarreaub4c84932013-07-23 19:15:30 +02006556 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006557 continue;
6558
6559 if (trule->act_prm.trk_ctr.table.n)
6560 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6561 else
6562 target = curproxy;
6563
6564 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006565 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6566 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006567 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006568 cfgerr++;
6569 }
6570 else if (target->table.size == 0) {
6571 Alert("Proxy '%s': table '%s' used but not configured.\n",
6572 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6573 cfgerr++;
6574 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006575 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6576 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6577 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 +01006578 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006579 cfgerr++;
6580 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006581 else {
6582 free(trule->act_prm.trk_ctr.table.n);
6583 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006584 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006585 * to pass a list of counters to track and allocate them right here using
6586 * stktable_alloc_data_type().
6587 */
6588 }
6589 }
6590
Willy Tarreau09448f72014-06-25 18:12:15 +02006591 /* find the target table for 'http-request' layer 7 rules */
6592 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6593 struct proxy *target;
6594
6595 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6596 continue;
6597
6598 if (hrqrule->act_prm.trk_ctr.table.n)
6599 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6600 else
6601 target = curproxy;
6602
6603 if (!target) {
6604 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6605 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6606 http_req_trk_idx(hrqrule->action));
6607 cfgerr++;
6608 }
6609 else if (target->table.size == 0) {
6610 Alert("Proxy '%s': table '%s' used but not configured.\n",
6611 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6612 cfgerr++;
6613 }
6614 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6615 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6616 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6617 http_req_trk_idx(hrqrule->action));
6618 cfgerr++;
6619 }
6620 else {
6621 free(hrqrule->act_prm.trk_ctr.table.n);
6622 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6623 /* Note: if we decide to enhance the track-sc syntax, we may be able
6624 * to pass a list of counters to track and allocate them right here using
6625 * stktable_alloc_data_type().
6626 */
6627 }
6628 }
6629
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006630 /* move any "block" rules at the beginning of the http-request rules */
6631 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6632 /* insert block_rules into http_req_rules at the beginning */
6633 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6634 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6635 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6636 curproxy->http_req_rules.n = curproxy->block_rules.n;
6637 LIST_INIT(&curproxy->block_rules);
6638 }
6639
Emeric Brun32da3c42010-09-23 18:39:19 +02006640 if (curproxy->table.peers.name) {
6641 struct peers *curpeers = peers;
6642
6643 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6644 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6645 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006646 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006647 break;
6648 }
6649 }
6650
6651 if (!curpeers) {
6652 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6653 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006654 free((void *)curproxy->table.peers.name);
6655 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006656 cfgerr++;
6657 }
6658 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006659 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6660 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006661 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006662 cfgerr++;
6663 }
6664 }
6665
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006666 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006667 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006668 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6669 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6670 "proxy", curproxy->id);
6671 cfgerr++;
6672 goto out_uri_auth_compat;
6673 }
6674
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006675 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006676 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006677 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006678 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006679
Willy Tarreau95fa4692010-02-01 13:05:50 +01006680 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6681 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006682
6683 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006684 uri_auth_compat_req[i++] = "realm";
6685 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6686 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006687
Willy Tarreau95fa4692010-02-01 13:05:50 +01006688 uri_auth_compat_req[i++] = "unless";
6689 uri_auth_compat_req[i++] = "{";
6690 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6691 uri_auth_compat_req[i++] = "}";
6692 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006693
Willy Tarreauff011f22011-01-06 17:51:27 +01006694 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6695 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006696 cfgerr++;
6697 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006698 }
6699
Willy Tarreauff011f22011-01-06 17:51:27 +01006700 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006701
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006702 if (curproxy->uri_auth->auth_realm) {
6703 free(curproxy->uri_auth->auth_realm);
6704 curproxy->uri_auth->auth_realm = NULL;
6705 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006706
6707 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006708 }
6709out_uri_auth_compat:
6710
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006711 /* compile the log format */
6712 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006713 if (curproxy->conf.logformat_string != default_http_log_format &&
6714 curproxy->conf.logformat_string != default_tcp_log_format &&
6715 curproxy->conf.logformat_string != clf_http_log_format)
6716 free(curproxy->conf.logformat_string);
6717 curproxy->conf.logformat_string = NULL;
6718 free(curproxy->conf.lfs_file);
6719 curproxy->conf.lfs_file = NULL;
6720 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006721 }
6722
Willy Tarreau62a61232013-04-12 18:13:46 +02006723 if (curproxy->conf.logformat_string) {
6724 curproxy->conf.args.ctx = ARGC_LOG;
6725 curproxy->conf.args.file = curproxy->conf.lfs_file;
6726 curproxy->conf.args.line = curproxy->conf.lfs_line;
6727 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006728 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006729 curproxy->conf.args.file = NULL;
6730 curproxy->conf.args.line = 0;
6731 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006732
Willy Tarreau62a61232013-04-12 18:13:46 +02006733 if (curproxy->conf.uniqueid_format_string) {
6734 curproxy->conf.args.ctx = ARGC_UIF;
6735 curproxy->conf.args.file = curproxy->conf.uif_file;
6736 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006737 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006738 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6739 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006740 curproxy->conf.args.file = NULL;
6741 curproxy->conf.args.line = 0;
6742 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006743
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006744 /* only now we can check if some args remain unresolved.
6745 * This must be done after the users and groups resolution.
6746 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006747 cfgerr += smp_resolve_args(curproxy);
6748 if (!cfgerr)
6749 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006750
Willy Tarreau2738a142006-07-08 17:28:09 +02006751 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006752 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006753 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006754 (!curproxy->timeout.connect ||
6755 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006756 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006757 " | While not properly invalid, you will certainly encounter various problems\n"
6758 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006759 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006760 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006761 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006762 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006763
Willy Tarreau1fa31262007-12-03 00:36:16 +01006764 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6765 * We must still support older configurations, so let's find out whether those
6766 * parameters have been set or must be copied from contimeouts.
6767 */
6768 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006769 if (!curproxy->timeout.tarpit ||
6770 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006771 /* tarpit timeout not set. We search in the following order:
6772 * default.tarpit, curr.connect, default.connect.
6773 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006774 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006775 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006776 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006777 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006778 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006779 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006780 }
6781 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006782 (!curproxy->timeout.queue ||
6783 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006784 /* queue timeout not set. We search in the following order:
6785 * default.queue, curr.connect, default.connect.
6786 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006787 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006788 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006789 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006790 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006791 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006792 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006793 }
6794 }
6795
Willy Tarreau1620ec32011-08-06 17:05:02 +02006796 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006797 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6798 curproxy->check_req = (char *)malloc(curproxy->check_len);
6799 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006800 }
6801
Willy Tarreau215663d2014-06-13 18:30:23 +02006802 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6803 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6804 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6805 proxy_type_str(curproxy), curproxy->id);
6806 err_code |= ERR_WARN;
6807 }
6808
Willy Tarreau193b8c62012-11-22 00:17:38 +01006809 /* ensure that cookie capture length is not too large */
6810 if (curproxy->capture_len >= global.tune.cookie_len) {
6811 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6812 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6813 err_code |= ERR_WARN;
6814 curproxy->capture_len = global.tune.cookie_len - 1;
6815 }
6816
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006817 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006818 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006819 curproxy->req_cap_pool = create_pool("ptrcap",
6820 curproxy->nb_req_cap * sizeof(char *),
6821 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006822 }
6823
6824 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006825 curproxy->rsp_cap_pool = create_pool("ptrcap",
6826 curproxy->nb_rsp_cap * sizeof(char *),
6827 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006828 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006829
Willy Tarreaubaaee002006-06-26 02:48:02 +02006830 /* first, we will invert the servers list order */
6831 newsrv = NULL;
6832 while (curproxy->srv) {
6833 struct server *next;
6834
6835 next = curproxy->srv->next;
6836 curproxy->srv->next = newsrv;
6837 newsrv = curproxy->srv;
6838 if (!next)
6839 break;
6840 curproxy->srv = next;
6841 }
6842
Willy Tarreau17edc812014-01-03 12:14:34 +01006843 /* Check that no server name conflicts. This causes trouble in the stats.
6844 * We only emit a warning for the first conflict affecting each server,
6845 * in order to avoid combinatory explosion if all servers have the same
6846 * name. We do that only for servers which do not have an explicit ID,
6847 * because these IDs were made also for distinguishing them and we don't
6848 * want to annoy people who correctly manage them.
6849 */
6850 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6851 struct server *other_srv;
6852
6853 if (newsrv->puid)
6854 continue;
6855
6856 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6857 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6858 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6859 newsrv->conf.file, newsrv->conf.line,
6860 proxy_type_str(curproxy), curproxy->id,
6861 newsrv->id, other_srv->conf.line);
6862 break;
6863 }
6864 }
6865 }
6866
Willy Tarreaudd701652010-05-25 23:03:02 +02006867 /* assign automatic UIDs to servers which don't have one yet */
6868 next_id = 1;
6869 newsrv = curproxy->srv;
6870 while (newsrv != NULL) {
6871 if (!newsrv->puid) {
6872 /* server ID not set, use automatic numbering with first
6873 * spare entry starting with next_svid.
6874 */
6875 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6876 newsrv->conf.id.key = newsrv->puid = next_id;
6877 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6878 }
6879 next_id++;
6880 newsrv = newsrv->next;
6881 }
6882
Willy Tarreau20697042007-11-15 23:26:18 +01006883 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006884 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006885
Willy Tarreau62c3be22012-01-20 13:12:32 +01006886 /*
6887 * If this server supports a maxconn parameter, it needs a dedicated
6888 * tasks to fill the emptied slots when a connection leaves.
6889 * Also, resolve deferred tracking dependency if needed.
6890 */
6891 newsrv = curproxy->srv;
6892 while (newsrv != NULL) {
6893 if (newsrv->minconn > newsrv->maxconn) {
6894 /* Only 'minconn' was specified, or it was higher than or equal
6895 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6896 * this will avoid further useless expensive computations.
6897 */
6898 newsrv->maxconn = newsrv->minconn;
6899 } else if (newsrv->maxconn && !newsrv->minconn) {
6900 /* minconn was not specified, so we set it to maxconn */
6901 newsrv->minconn = newsrv->maxconn;
6902 }
6903
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006904#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006905 if (newsrv->use_ssl || newsrv->check.use_ssl)
6906 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006907#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006908
Willy Tarreau2f075e92013-12-03 11:11:34 +01006909 /* set the check type on the server */
6910 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6911
Willy Tarreau62c3be22012-01-20 13:12:32 +01006912 if (newsrv->trackit) {
6913 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006914 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006915 char *pname, *sname;
6916
6917 pname = newsrv->trackit;
6918 sname = strrchr(pname, '/');
6919
6920 if (sname)
6921 *sname++ = '\0';
6922 else {
6923 sname = pname;
6924 pname = NULL;
6925 }
6926
6927 if (pname) {
6928 px = findproxy(pname, PR_CAP_BE);
6929 if (!px) {
6930 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6931 proxy_type_str(curproxy), curproxy->id,
6932 newsrv->id, pname);
6933 cfgerr++;
6934 goto next_srv;
6935 }
6936 } else
6937 px = curproxy;
6938
6939 srv = findserver(px, sname);
6940 if (!srv) {
6941 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6942 proxy_type_str(curproxy), curproxy->id,
6943 newsrv->id, sname);
6944 cfgerr++;
6945 goto next_srv;
6946 }
6947
Willy Tarreau32091232014-05-16 13:52:00 +02006948 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6949 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6950 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006951 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006952 "tracking as it does not have any check nor agent enabled.\n",
6953 proxy_type_str(curproxy), curproxy->id,
6954 newsrv->id, px->id, srv->id);
6955 cfgerr++;
6956 goto next_srv;
6957 }
6958
6959 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6960
6961 if (loop) {
6962 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6963 "belongs to a tracking chain looping back to %s/%s.\n",
6964 proxy_type_str(curproxy), curproxy->id,
6965 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006966 cfgerr++;
6967 goto next_srv;
6968 }
6969
6970 if (curproxy != px &&
6971 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6972 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6973 "tracking: disable-on-404 option inconsistency.\n",
6974 proxy_type_str(curproxy), curproxy->id,
6975 newsrv->id, px->id, srv->id);
6976 cfgerr++;
6977 goto next_srv;
6978 }
6979
6980 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006981 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006982 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006983 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006984 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006985 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006986 }
6987
6988 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006989 newsrv->tracknext = srv->trackers;
6990 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006991
6992 free(newsrv->trackit);
6993 newsrv->trackit = NULL;
6994 }
6995 next_srv:
6996 newsrv = newsrv->next;
6997 }
6998
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006999 /* We have to initialize the server lookup mechanism depending
7000 * on what LB algorithm was choosen.
7001 */
7002
7003 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7004 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7005 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007006 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7007 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7008 init_server_map(curproxy);
7009 } else {
7010 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7011 fwrr_init_server_groups(curproxy);
7012 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007013 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007014
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007015 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007016 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7017 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7018 fwlc_init_server_tree(curproxy);
7019 } else {
7020 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7021 fas_init_server_tree(curproxy);
7022 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007023 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007024
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007025 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007026 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7027 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7028 chash_init_server_tree(curproxy);
7029 } else {
7030 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7031 init_server_map(curproxy);
7032 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007033 break;
7034 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007035
7036 if (curproxy->options & PR_O_LOGASAP)
7037 curproxy->to_log &= ~LW_BYTES;
7038
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007039 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007040 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007041 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7042 proxy_type_str(curproxy), curproxy->id);
7043 err_code |= ERR_WARN;
7044 }
7045
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007046 if (curproxy->mode != PR_MODE_HTTP) {
7047 int optnum;
7048
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007049 if (curproxy->uri_auth) {
7050 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7051 proxy_type_str(curproxy), curproxy->id);
7052 err_code |= ERR_WARN;
7053 curproxy->uri_auth = NULL;
7054 }
7055
Willy Tarreau87cf5142011-08-19 22:57:24 +02007056 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007057 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7058 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7059 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007060 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007061 }
7062
7063 if (curproxy->options & PR_O_ORGTO) {
7064 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7065 "originalto", proxy_type_str(curproxy), curproxy->id);
7066 err_code |= ERR_WARN;
7067 curproxy->options &= ~PR_O_ORGTO;
7068 }
7069
7070 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7071 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7072 (curproxy->cap & cfg_opts[optnum].cap) &&
7073 (curproxy->options & cfg_opts[optnum].val)) {
7074 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7075 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7076 err_code |= ERR_WARN;
7077 curproxy->options &= ~cfg_opts[optnum].val;
7078 }
7079 }
7080
7081 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7082 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7083 (curproxy->cap & cfg_opts2[optnum].cap) &&
7084 (curproxy->options2 & cfg_opts2[optnum].val)) {
7085 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7086 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7087 err_code |= ERR_WARN;
7088 curproxy->options2 &= ~cfg_opts2[optnum].val;
7089 }
7090 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007091
Pieter Baauwd551fb52013-05-08 22:49:23 +02007092#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007093 if (curproxy->conn_src.bind_hdr_occ) {
7094 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007095 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007096 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007097 err_code |= ERR_WARN;
7098 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007099#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007100 }
7101
Willy Tarreaubaaee002006-06-26 02:48:02 +02007102 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007103 * ensure that we're not cross-dressing a TCP server into HTTP.
7104 */
7105 newsrv = curproxy->srv;
7106 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007107 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007108 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7109 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007110 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007111 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007112
Willy Tarreau0cec3312011-10-31 13:49:26 +01007113 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7114 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7115 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7116 err_code |= ERR_WARN;
7117 }
7118
Willy Tarreauc93cd162014-05-13 15:54:22 +02007119 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007120 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7121 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7122 err_code |= ERR_WARN;
7123 }
7124
Pieter Baauwd551fb52013-05-08 22:49:23 +02007125#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007126 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7127 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007128 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 +01007129 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007130 err_code |= ERR_WARN;
7131 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007132#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007133 newsrv = newsrv->next;
7134 }
7135
Willy Tarreaue42bd962014-09-16 16:21:19 +02007136 /* check if we have a frontend with "tcp-request content" looking at L7
7137 * with no inspect-delay
7138 */
7139 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7140 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7141 if (trule->action == TCP_ACT_CAPTURE &&
7142 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7143 break;
7144 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7145 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7146 break;
7147 }
7148
7149 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7150 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7151 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7152 " This means that these rules will randomly find their contents. This can be fixed by"
7153 " setting the tcp-request inspect-delay.\n",
7154 proxy_type_str(curproxy), curproxy->id);
7155 err_code |= ERR_WARN;
7156 }
7157 }
7158
Willy Tarreauc1a21672009-08-16 22:37:44 +02007159 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007160 if (!curproxy->accept)
7161 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007162
Willy Tarreauc1a21672009-08-16 22:37:44 +02007163 if (curproxy->tcp_req.inspect_delay ||
7164 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007165 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007166
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007167 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007168 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007169 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007170 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007171
7172 /* both TCP and HTTP must check switching rules */
7173 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7174 }
7175
7176 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007177 if (curproxy->tcp_req.inspect_delay ||
7178 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7179 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7180
Emeric Brun97679e72010-09-23 17:56:44 +02007181 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7182 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7183
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007184 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007185 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007186 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007187 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007188
7189 /* If the backend does requires RDP cookie persistence, we have to
7190 * enable the corresponding analyser.
7191 */
7192 if (curproxy->options2 & PR_O2_RDPC_PRST)
7193 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7194 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007195 }
7196
7197 /***********************************************************/
7198 /* At this point, target names have already been resolved. */
7199 /***********************************************************/
7200
7201 /* Check multi-process mode compatibility */
7202
7203 if (global.nbproc > 1 && global.stats_fe) {
7204 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7205 unsigned long mask;
7206
7207 mask = nbits(global.nbproc);
7208 if (global.stats_fe->bind_proc)
7209 mask &= global.stats_fe->bind_proc;
7210
7211 if (bind_conf->bind_proc)
7212 mask &= bind_conf->bind_proc;
7213
7214 /* stop here if more than one process is used */
7215 if (popcount(mask) > 1)
7216 break;
7217 }
7218 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7219 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");
7220 }
7221 }
7222
7223 /* Make each frontend inherit bind-process from its listeners when not specified. */
7224 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7225 if (curproxy->bind_proc)
7226 continue;
7227
7228 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7229 unsigned long mask;
7230
7231 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7232 curproxy->bind_proc |= mask;
7233 }
7234
7235 if (!curproxy->bind_proc)
7236 curproxy->bind_proc = ~0UL;
7237 }
7238
7239 if (global.stats_fe) {
7240 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7241 unsigned long mask;
7242
7243 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7244 global.stats_fe->bind_proc |= mask;
7245 }
7246 if (!global.stats_fe->bind_proc)
7247 global.stats_fe->bind_proc = ~0UL;
7248 }
7249
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007250 /* propagate bindings from frontends to backends. Don't do it if there
7251 * are any fatal errors as we must not call it with unresolved proxies.
7252 */
7253 if (!cfgerr) {
7254 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7255 if (curproxy->cap & PR_CAP_FE)
7256 propagate_processes(curproxy, NULL);
7257 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007258 }
7259
7260 /* Bind each unbound backend to all processes when not specified. */
7261 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7262 if (curproxy->bind_proc)
7263 continue;
7264 curproxy->bind_proc = ~0UL;
7265 }
7266
7267 /*******************************************************/
7268 /* At this step, all proxies have a non-null bind_proc */
7269 /*******************************************************/
7270
7271 /* perform the final checks before creating tasks */
7272
7273 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7274 struct listener *listener;
7275 unsigned int next_id;
7276 int nbproc;
7277
7278 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007279
Emeric Brunc52962f2012-11-15 18:28:02 +01007280#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007281 /* Configure SSL for each bind line.
7282 * Note: if configuration fails at some point, the ->ctx member
7283 * remains NULL so that listeners can later detach.
7284 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007285 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007286 int alloc_ctx;
7287
Emeric Brunc52962f2012-11-15 18:28:02 +01007288 if (!bind_conf->is_ssl) {
7289 if (bind_conf->default_ctx) {
7290 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7291 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7292 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007293 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007294 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007295 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007296 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007297 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007298 cfgerr++;
7299 continue;
7300 }
7301
Emeric Brun8dc60392014-05-09 13:52:00 +02007302 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007303 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007304 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7305 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");
7306 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007307 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007308 cfgerr++;
7309 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007310 }
7311
Emeric Brunfc0421f2012-09-07 17:30:07 +02007312 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007313 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007314 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007315#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007316
Willy Tarreaue6b98942007-10-29 01:09:36 +01007317 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007318 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007319 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007320 if (!listener->luid) {
7321 /* listener ID not set, use automatic numbering with first
7322 * spare entry starting with next_luid.
7323 */
7324 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7325 listener->conf.id.key = listener->luid = next_id;
7326 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007327 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007328 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007329
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007330 /* enable separate counters */
7331 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7332 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007333 if (!listener->name)
7334 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007335 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007336
Willy Tarreaue6b98942007-10-29 01:09:36 +01007337 if (curproxy->options & PR_O_TCP_NOLING)
7338 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007339 if (!listener->maxconn)
7340 listener->maxconn = curproxy->maxconn;
7341 if (!listener->backlog)
7342 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007343 if (!listener->maxaccept)
7344 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7345
7346 /* we want to have an optimal behaviour on single process mode to
7347 * maximize the work at once, but in multi-process we want to keep
7348 * some fairness between processes, so we target half of the max
7349 * number of events to be balanced over all the processes the proxy
7350 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7351 * used to disable the limit.
7352 */
7353 if (listener->maxaccept > 0) {
7354 if (nbproc > 1)
7355 listener->maxaccept = (listener->maxaccept + 1) / 2;
7356 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7357 }
7358
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007359 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007360 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007361 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007362 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007363
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007364 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7365 listener->options |= LI_O_TCP_RULES;
7366
Willy Tarreaude3041d2010-05-31 10:56:17 +02007367 if (curproxy->mon_mask.s_addr)
7368 listener->options |= LI_O_CHK_MONNET;
7369
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007370 /* smart accept mode is automatic in HTTP mode */
7371 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007372 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007373 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7374 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007375 }
7376
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007377 /* Release unused SSL configs */
7378 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7379 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007380 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007381#ifdef USE_OPENSSL
7382 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007383 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007384 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007385 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007386 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007387#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007388 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007389
Willy Tarreau102df612014-05-07 23:56:38 +02007390 if (nbproc > 1) {
7391 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02007392 int count, maxproc = 0;
7393
7394 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7395 count = popcount(bind_conf->bind_proc);
7396 if (count > maxproc)
7397 maxproc = count;
7398 }
7399 /* backends have 0, frontends have 1 or more */
7400 if (maxproc != 1)
7401 Warning("Proxy '%s': in multi-process mode, stats will be"
7402 " limited to process assigned to the current request.\n",
7403 curproxy->id);
7404
Willy Tarreau102df612014-05-07 23:56:38 +02007405 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7406 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7407 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007408 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007409 }
Willy Tarreau102df612014-05-07 23:56:38 +02007410 if (curproxy->appsession_name) {
7411 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7412 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007413 }
Willy Tarreau102df612014-05-07 23:56:38 +02007414 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7415 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7416 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007417 }
7418 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007419
7420 /* create the task associated with the proxy */
7421 curproxy->task = task_new();
7422 if (curproxy->task) {
7423 curproxy->task->context = curproxy;
7424 curproxy->task->process = manage_proxy;
7425 /* no need to queue, it will be done automatically if some
7426 * listener gets limited.
7427 */
7428 curproxy->task->expire = TICK_ETERNITY;
7429 } else {
7430 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7431 curproxy->id);
7432 cfgerr++;
7433 }
Willy Tarreaub369a042014-09-16 13:21:03 +02007434 }
7435
Willy Tarreaufbb78422011-06-05 15:38:35 +02007436 /* automatically compute fullconn if not set. We must not do it in the
7437 * loop above because cross-references are not yet fully resolved.
7438 */
7439 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7440 /* If <fullconn> is not set, let's set it to 10% of the sum of
7441 * the possible incoming frontend's maxconns.
7442 */
7443 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7444 struct proxy *fe;
7445 int total = 0;
7446
7447 /* sum up the number of maxconns of frontends which
7448 * reference this backend at least once or which are
7449 * the same one ('listen').
7450 */
7451 for (fe = proxy; fe; fe = fe->next) {
7452 struct switching_rule *rule;
7453 struct hdr_exp *exp;
7454 int found = 0;
7455
7456 if (!(fe->cap & PR_CAP_FE))
7457 continue;
7458
7459 if (fe == curproxy) /* we're on a "listen" instance */
7460 found = 1;
7461
7462 if (fe->defbe.be == curproxy) /* "default_backend" */
7463 found = 1;
7464
7465 /* check if a "use_backend" rule matches */
7466 if (!found) {
7467 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007468 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007469 found = 1;
7470 break;
7471 }
7472 }
7473 }
7474
7475 /* check if a "reqsetbe" rule matches */
7476 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7477 if (exp->action == ACT_SETBE &&
7478 (struct proxy *)exp->replace == curproxy) {
7479 found = 1;
7480 break;
7481 }
7482 }
7483
7484 /* now we've checked all possible ways to reference a backend
7485 * from a frontend.
7486 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007487 if (!found)
7488 continue;
7489 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007490 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007491 /* we have the sum of the maxconns in <total>. We only
7492 * keep 10% of that sum to set the default fullconn, with
7493 * a hard minimum of 1 (to avoid a divide by zero).
7494 */
7495 curproxy->fullconn = (total + 9) / 10;
7496 if (!curproxy->fullconn)
7497 curproxy->fullconn = 1;
7498 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007499 }
7500
Willy Tarreau056f5682010-06-06 15:51:11 +02007501 /* initialize stick-tables on backend capable proxies. This must not
7502 * be done earlier because the data size may be discovered while parsing
7503 * other proxies.
7504 */
Godbach9703e662013-12-11 21:11:41 +08007505 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007506 if (curproxy->state == PR_STSTOPPED)
7507 continue;
7508
Godbach9703e662013-12-11 21:11:41 +08007509 if (!stktable_init(&curproxy->table)) {
7510 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7511 cfgerr++;
7512 }
7513 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007514
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007515 /*
7516 * Recount currently required checks.
7517 */
7518
7519 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7520 int optnum;
7521
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007522 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7523 if (curproxy->options & cfg_opts[optnum].val)
7524 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007525
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007526 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7527 if (curproxy->options2 & cfg_opts2[optnum].val)
7528 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007529 }
7530
Willy Tarreau122541c2011-09-07 21:24:49 +02007531 if (peers) {
7532 struct peers *curpeers = peers, **last;
7533 struct peer *p, *pb;
7534
7535 /* Remove all peers sections which don't have a valid listener.
7536 * This can happen when a peers section is never referenced and
7537 * does not contain a local peer.
7538 */
7539 last = &peers;
7540 while (*last) {
7541 curpeers = *last;
7542 if (curpeers->peers_fe) {
7543 last = &curpeers->next;
7544 continue;
7545 }
7546
7547 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7548 curpeers->id, localpeer);
7549
7550 p = curpeers->remote;
7551 while (p) {
7552 pb = p->next;
7553 free(p->id);
7554 free(p);
7555 p = pb;
7556 }
7557
7558 /* Destroy and unlink this curpeers section.
7559 * Note: curpeers is backed up into *last.
7560 */
7561 free(curpeers->id);
7562 curpeers = curpeers->next;
7563 free(*last);
7564 *last = curpeers;
7565 }
7566 }
7567
Willy Tarreau34eb6712011-10-24 18:15:04 +02007568 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007569 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007570 MEM_F_SHARED);
7571
Willy Tarreaubb925012009-07-23 13:36:36 +02007572 if (cfgerr > 0)
7573 err_code |= ERR_ALERT | ERR_FATAL;
7574 out:
7575 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007576}
7577
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007578/*
7579 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7580 * parsing sessions.
7581 */
7582void cfg_register_keywords(struct cfg_kw_list *kwl)
7583{
7584 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7585}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007586
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007587/*
7588 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7589 */
7590void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7591{
7592 LIST_DEL(&kwl->list);
7593 LIST_INIT(&kwl->list);
7594}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007595
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007596/* this function register new section in the haproxy configuration file.
7597 * <section_name> is the name of this new section and <section_parser>
7598 * is the called parser. If two section declaration have the same name,
7599 * only the first declared is used.
7600 */
7601int cfg_register_section(char *section_name,
7602 int (*section_parser)(const char *, int, char **, int))
7603{
7604 struct cfg_section *cs;
7605
7606 cs = calloc(1, sizeof(*cs));
7607 if (!cs) {
7608 Alert("register section '%s': out of memory.\n", section_name);
7609 return 0;
7610 }
7611
7612 cs->section_name = section_name;
7613 cs->section_parser = section_parser;
7614
7615 LIST_ADDQ(&sections, &cs->list);
7616
7617 return 1;
7618}
7619
Willy Tarreaubaaee002006-06-26 02:48:02 +02007620/*
7621 * Local variables:
7622 * c-indent-level: 8
7623 * c-basic-offset: 8
7624 * End:
7625 */