blob: b9853ef208bb91a590877151095036935bc8f008 [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é2c8d7002014-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 Tarreau61d18892009-03-31 10:49:21 +0200320/* Report a warning if a rule is placed after a 'block' rule.
321 * Return 1 if the warning has been emitted, otherwise 0.
322 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100323int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200324{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200325 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200326 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
327 file, line, arg);
328 return 1;
329 }
330 return 0;
331}
332
Willy Tarreau5002f572014-04-23 01:32:02 +0200333/* Report a warning if a rule is placed after an 'http_request' rule.
334 * Return 1 if the warning has been emitted, otherwise 0.
335 */
336int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
337{
338 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
339 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
340 file, line, arg);
341 return 1;
342 }
343 return 0;
344}
345
Willy Tarreau61d18892009-03-31 10:49:21 +0200346/* Report a warning if a rule is placed after a reqrewrite rule.
347 * Return 1 if the warning has been emitted, otherwise 0.
348 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100349int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200350{
351 if (proxy->req_exp) {
352 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
353 file, line, arg);
354 return 1;
355 }
356 return 0;
357}
358
359/* Report a warning if a rule is placed after a reqadd rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100362int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200363{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100364 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' 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 redirect rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
377 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' 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 'use_backend' rule.
386 * Return 1 if the warning has been emitted, otherwise 0.
387 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100388int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200389{
390 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
391 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
392 file, line, arg);
393 return 1;
394 }
395 return 0;
396}
397
Willy Tarreauee445d92014-04-23 01:39:04 +0200398/* Report a warning if a rule is placed after a 'use-server' rule.
399 * Return 1 if the warning has been emitted, otherwise 0.
400 */
401int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
402{
403 if (!LIST_ISEMPTY(&proxy->server_rules)) {
404 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
405 file, line, arg);
406 return 1;
407 }
408 return 0;
409}
410
Willy Tarreau61d18892009-03-31 10:49:21 +0200411/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
Willy Tarreau5002f572014-04-23 01:32:02 +0200414 return warnif_rule_after_http_req(proxy, file, line, arg) ||
415 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
416 warnif_rule_after_reqadd(proxy, file, line, arg) ||
417 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200418 warnif_rule_after_use_backend(proxy, file, line, arg) ||
419 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200420}
421
422/* report a warning if an http-request rule is dangerously placed */
423int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
424{
Willy Tarreau61d18892009-03-31 10:49:21 +0200425 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
426 warnif_rule_after_reqadd(proxy, file, line, arg) ||
427 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200428 warnif_rule_after_use_backend(proxy, file, line, arg) ||
429 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200430}
431
432/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100433int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200434{
435 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
436 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200437 warnif_rule_after_use_backend(proxy, file, line, arg) ||
438 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200439}
440
441/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100442int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200443{
444 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200445 warnif_rule_after_use_backend(proxy, file, line, arg) ||
446 warnif_rule_after_use_server(proxy, file, line, arg);
447}
448
449/* report a warning if a redirect rule is dangerously placed */
450int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
451{
452 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
453 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200454}
455
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100456/* Report it if a request ACL condition uses some keywords that are incompatible
457 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
458 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
459 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100460 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100461static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100462{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100463 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200464 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100465
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100466 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100467 return 0;
468
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100469 acl = acl_cond_conflicts(cond, where);
470 if (acl) {
471 if (acl->name && *acl->name)
472 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
473 file, line, acl->name, sample_ckp_names(where));
474 else
475 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 +0200476 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100477 return ERR_WARN;
478 }
479 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100480 return 0;
481
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100482 if (acl->name && *acl->name)
483 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200484 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100485 else
486 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200487 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100488 return ERR_WARN;
489}
490
Willy Tarreaubaaee002006-06-26 02:48:02 +0200491/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200492 * parse a line in a <global> section. Returns the error code, 0 if OK, or
493 * any combination of :
494 * - ERR_ABORT: must abort ASAP
495 * - ERR_FATAL: we can continue parsing but not start the service
496 * - ERR_WARN: a warning has been emitted
497 * - ERR_ALERT: an alert has been emitted
498 * Only the two first ones can stop processing, the two others are just
499 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200500 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200501int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200502{
Willy Tarreau058e9072009-07-20 09:30:05 +0200503 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200504 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200505
506 if (!strcmp(args[0], "global")) { /* new section */
507 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200510 else if (!strcmp(args[0], "ca-base")) {
511#ifdef USE_OPENSSL
512 if (global.ca_base != NULL) {
513 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
514 err_code |= ERR_ALERT;
515 goto out;
516 }
517 if (*(args[1]) == 0) {
518 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
519 err_code |= ERR_ALERT | ERR_FATAL;
520 goto out;
521 }
522 global.ca_base = strdup(args[1]);
523#else
524 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
525 err_code |= ERR_ALERT | ERR_FATAL;
526 goto out;
527#endif
528 }
529 else if (!strcmp(args[0], "crt-base")) {
530#ifdef USE_OPENSSL
531 if (global.crt_base != NULL) {
532 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
533 err_code |= ERR_ALERT;
534 goto out;
535 }
536 if (*(args[1]) == 0) {
537 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
540 }
541 global.crt_base = strdup(args[1]);
542#else
543 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
544 err_code |= ERR_ALERT | ERR_FATAL;
545 goto out;
546#endif
547 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548 else if (!strcmp(args[0], "daemon")) {
549 global.mode |= MODE_DAEMON;
550 }
551 else if (!strcmp(args[0], "debug")) {
552 global.mode |= MODE_DEBUG;
553 }
554 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100555 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200556 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200557 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100558 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200559 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200560 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100561 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200562 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100563 else if (!strcmp(args[0], "nosplice")) {
564 global.tune.options &= ~GTUNE_USE_SPLICE;
565 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200566 else if (!strcmp(args[0], "nogetaddrinfo")) {
567 global.tune.options &= ~GTUNE_USE_GAI;
568 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200569 else if (!strcmp(args[0], "quiet")) {
570 global.mode |= MODE_QUIET;
571 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200572 else if (!strcmp(args[0], "tune.maxpollevents")) {
573 if (global.tune.maxpollevents != 0) {
574 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200575 err_code |= ERR_ALERT;
576 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200577 }
578 if (*(args[1]) == 0) {
579 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200580 err_code |= ERR_ALERT | ERR_FATAL;
581 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200582 }
583 global.tune.maxpollevents = atol(args[1]);
584 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100585 else if (!strcmp(args[0], "tune.maxaccept")) {
586 if (global.tune.maxaccept != 0) {
587 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200588 err_code |= ERR_ALERT;
589 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100590 }
591 if (*(args[1]) == 0) {
592 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200593 err_code |= ERR_ALERT | ERR_FATAL;
594 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100595 }
596 global.tune.maxaccept = atol(args[1]);
597 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200598 else if (!strcmp(args[0], "tune.chksize")) {
599 if (*(args[1]) == 0) {
600 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
601 err_code |= ERR_ALERT | ERR_FATAL;
602 goto out;
603 }
604 global.tune.chksize = atol(args[1]);
605 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200606#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200607 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
608 global.tune.sslprivatecache = 1;
609 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100610 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200611 if (*(args[1]) == 0) {
612 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
613 err_code |= ERR_ALERT | ERR_FATAL;
614 goto out;
615 }
616 global.tune.sslcachesize = atol(args[1]);
617 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100618 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
619 unsigned int ssllifetime;
620 const char *res;
621
622 if (*(args[1]) == 0) {
623 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT | ERR_FATAL;
625 goto out;
626 }
627
628 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
629 if (res) {
630 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
631 file, linenum, *res, args[0]);
632 err_code |= ERR_ALERT | ERR_FATAL;
633 goto out;
634 }
635
636 global.tune.ssllifetime = ssllifetime;
637 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100638 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
639 if (*(args[1]) == 0) {
640 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
641 err_code |= ERR_ALERT | ERR_FATAL;
642 goto out;
643 }
644 global.tune.ssl_max_record = atol(args[1]);
645 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200646 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
647 if (*(args[1]) == 0) {
648 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
649 err_code |= ERR_ALERT | ERR_FATAL;
650 goto out;
651 }
652 global.tune.ssl_default_dh_param = atol(args[1]);
653 if (global.tune.ssl_default_dh_param < 1024) {
654 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
655 err_code |= ERR_ALERT | ERR_FATAL;
656 goto out;
657 }
658 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200659#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200660 else if (!strcmp(args[0], "tune.bufsize")) {
661 if (*(args[1]) == 0) {
662 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
665 }
666 global.tune.bufsize = atol(args[1]);
667 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
668 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100669 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100670 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200671 }
672 else if (!strcmp(args[0], "tune.maxrewrite")) {
673 if (*(args[1]) == 0) {
674 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
675 err_code |= ERR_ALERT | ERR_FATAL;
676 goto out;
677 }
678 global.tune.maxrewrite = atol(args[1]);
679 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
680 global.tune.maxrewrite = global.tune.bufsize / 2;
681 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100682 else if (!strcmp(args[0], "tune.idletimer")) {
683 unsigned int idle;
684 const char *res;
685
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
690 }
691
692 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
693 if (res) {
694 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
695 file, linenum, *res, args[0]);
696 err_code |= ERR_ALERT | ERR_FATAL;
697 goto out;
698 }
699
700 if (idle > 65535) {
701 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704 }
705 global.tune.idle_timer = idle;
706 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100707 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
708 if (global.tune.client_rcvbuf != 0) {
709 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT;
711 goto out;
712 }
713 if (*(args[1]) == 0) {
714 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
715 err_code |= ERR_ALERT | ERR_FATAL;
716 goto out;
717 }
718 global.tune.client_rcvbuf = atol(args[1]);
719 }
720 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
721 if (global.tune.server_rcvbuf != 0) {
722 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
723 err_code |= ERR_ALERT;
724 goto out;
725 }
726 if (*(args[1]) == 0) {
727 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 global.tune.server_rcvbuf = atol(args[1]);
732 }
733 else if (!strcmp(args[0], "tune.sndbuf.client")) {
734 if (global.tune.client_sndbuf != 0) {
735 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
736 err_code |= ERR_ALERT;
737 goto out;
738 }
739 if (*(args[1]) == 0) {
740 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
743 }
744 global.tune.client_sndbuf = atol(args[1]);
745 }
746 else if (!strcmp(args[0], "tune.sndbuf.server")) {
747 if (global.tune.server_sndbuf != 0) {
748 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
749 err_code |= ERR_ALERT;
750 goto out;
751 }
752 if (*(args[1]) == 0) {
753 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
754 err_code |= ERR_ALERT | ERR_FATAL;
755 goto out;
756 }
757 global.tune.server_sndbuf = atol(args[1]);
758 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200759 else if (!strcmp(args[0], "tune.pipesize")) {
760 if (*(args[1]) == 0) {
761 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764 }
765 global.tune.pipesize = atol(args[1]);
766 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100767 else if (!strcmp(args[0], "tune.http.cookielen")) {
768 if (*(args[1]) == 0) {
769 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
772 }
773 global.tune.cookie_len = atol(args[1]) + 1;
774 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200775 else if (!strcmp(args[0], "tune.http.maxhdr")) {
776 if (*(args[1]) == 0) {
777 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
778 err_code |= ERR_ALERT | ERR_FATAL;
779 goto out;
780 }
781 global.tune.max_http_hdr = atol(args[1]);
782 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100783 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
784#ifdef USE_ZLIB
785 if (*args[1]) {
786 global.tune.zlibmemlevel = atoi(args[1]);
787 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
788 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
789 file, linenum, args[0]);
790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
792 }
793 } else {
794 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
795 file, linenum, args[0]);
796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
798 }
799#else
800 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
801 err_code |= ERR_ALERT | ERR_FATAL;
802 goto out;
803#endif
804 }
805 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
806#ifdef USE_ZLIB
807 if (*args[1]) {
808 global.tune.zlibwindowsize = atoi(args[1]);
809 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
810 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
811 file, linenum, args[0]);
812 err_code |= ERR_ALERT | ERR_FATAL;
813 goto out;
814 }
815 } else {
816 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
817 file, linenum, args[0]);
818 err_code |= ERR_ALERT | ERR_FATAL;
819 goto out;
820 }
821#else
822 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
823 err_code |= ERR_ALERT | ERR_FATAL;
824 goto out;
825#endif
826 }
William Lallemandf3747832012-11-09 12:33:10 +0100827 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
828 if (*args[1]) {
829 global.tune.comp_maxlevel = atoi(args[1]);
830 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
831 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
832 file, linenum, args[0]);
833 err_code |= ERR_ALERT | ERR_FATAL;
834 goto out;
835 }
836 } else {
837 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
838 file, linenum, args[0]);
839 err_code |= ERR_ALERT | ERR_FATAL;
840 goto out;
841 }
842 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200843 else if (!strcmp(args[0], "uid")) {
844 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200845 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200846 err_code |= ERR_ALERT;
847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200848 }
849 if (*(args[1]) == 0) {
850 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200851 err_code |= ERR_ALERT | ERR_FATAL;
852 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200853 }
854 global.uid = atol(args[1]);
855 }
856 else if (!strcmp(args[0], "gid")) {
857 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200858 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200859 err_code |= ERR_ALERT;
860 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200861 }
862 if (*(args[1]) == 0) {
863 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200866 }
867 global.gid = atol(args[1]);
868 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200869 /* user/group name handling */
870 else if (!strcmp(args[0], "user")) {
871 struct passwd *ha_user;
872 if (global.uid != 0) {
873 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200874 err_code |= ERR_ALERT;
875 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200876 }
877 errno = 0;
878 ha_user = getpwnam(args[1]);
879 if (ha_user != NULL) {
880 global.uid = (int)ha_user->pw_uid;
881 }
882 else {
883 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 +0200884 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200885 }
886 }
887 else if (!strcmp(args[0], "group")) {
888 struct group *ha_group;
889 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200890 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200891 err_code |= ERR_ALERT;
892 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200893 }
894 errno = 0;
895 ha_group = getgrnam(args[1]);
896 if (ha_group != NULL) {
897 global.gid = (int)ha_group->gr_gid;
898 }
899 else {
900 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 +0200901 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200902 }
903 }
904 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200905 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200906 if (*(args[1]) == 0) {
907 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910 }
911 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100912 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
913 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
914 file, linenum, args[0], LONGBITS, global.nbproc);
915 err_code |= ERR_ALERT | ERR_FATAL;
916 goto out;
917 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 }
919 else if (!strcmp(args[0], "maxconn")) {
920 if (global.maxconn != 0) {
921 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200922 err_code |= ERR_ALERT;
923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 }
925 if (*(args[1]) == 0) {
926 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200927 err_code |= ERR_ALERT | ERR_FATAL;
928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 }
930 global.maxconn = atol(args[1]);
931#ifdef SYSTEM_MAXCONN
932 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
933 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);
934 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936 }
937#endif /* SYSTEM_MAXCONN */
938 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200939 else if (!strcmp(args[0], "maxsslconn")) {
940#ifdef USE_OPENSSL
941 if (*(args[1]) == 0) {
942 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
943 err_code |= ERR_ALERT | ERR_FATAL;
944 goto out;
945 }
946 global.maxsslconn = atol(args[1]);
947#else
Emeric Brun0914df82012-10-02 18:45:42 +0200948 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
949 err_code |= ERR_ALERT | ERR_FATAL;
950 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200951#endif
952 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100953 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
954#ifdef USE_OPENSSL
955 if (*(args[1]) == 0) {
956 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
957 err_code |= ERR_ALERT | ERR_FATAL;
958 goto out;
959 }
960 free(global.listen_default_ciphers);
961 global.listen_default_ciphers = strdup(args[1]);
962#else
963 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
964 err_code |= ERR_ALERT | ERR_FATAL;
965 goto out;
966#endif
967 }
968 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
969#ifdef USE_OPENSSL
970 if (*(args[1]) == 0) {
971 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
972 err_code |= ERR_ALERT | ERR_FATAL;
973 goto out;
974 }
975 free(global.connect_default_ciphers);
976 global.connect_default_ciphers = strdup(args[1]);
977#else
978 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
979 err_code |= ERR_ALERT | ERR_FATAL;
980 goto out;
981#endif
982 }
Emeric Brun850efd52014-01-29 12:24:34 +0100983 else if (!strcmp(args[0], "ssl-server-verify")) {
984 if (*(args[1]) == 0) {
985 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
986 err_code |= ERR_ALERT | ERR_FATAL;
987 goto out;
988 }
989 if (strcmp(args[1],"none") == 0)
990 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
991 else if (strcmp(args[1],"required") == 0)
992 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
993 else {
994 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
995 err_code |= ERR_ALERT | ERR_FATAL;
996 goto out;
997 }
998 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200999 else if (!strcmp(args[0], "maxconnrate")) {
1000 if (global.cps_lim != 0) {
1001 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1002 err_code |= ERR_ALERT;
1003 goto out;
1004 }
1005 if (*(args[1]) == 0) {
1006 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1007 err_code |= ERR_ALERT | ERR_FATAL;
1008 goto out;
1009 }
1010 global.cps_lim = atol(args[1]);
1011 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001012 else if (!strcmp(args[0], "maxsessrate")) {
1013 if (global.sps_lim != 0) {
1014 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1015 err_code |= ERR_ALERT;
1016 goto out;
1017 }
1018 if (*(args[1]) == 0) {
1019 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1020 err_code |= ERR_ALERT | ERR_FATAL;
1021 goto out;
1022 }
1023 global.sps_lim = atol(args[1]);
1024 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001025 else if (!strcmp(args[0], "maxsslrate")) {
1026 if (global.ssl_lim != 0) {
1027 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1028 err_code |= ERR_ALERT;
1029 goto out;
1030 }
1031 if (*(args[1]) == 0) {
1032 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1033 err_code |= ERR_ALERT | ERR_FATAL;
1034 goto out;
1035 }
1036 global.ssl_lim = atol(args[1]);
1037 }
William Lallemandd85f9172012-11-09 17:05:39 +01001038 else if (!strcmp(args[0], "maxcomprate")) {
1039 if (*(args[1]) == 0) {
1040 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1041 err_code |= ERR_ALERT | ERR_FATAL;
1042 goto out;
1043 }
1044 global.comp_rate_lim = atoi(args[1]) * 1024;
1045 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001046 else if (!strcmp(args[0], "maxpipes")) {
1047 if (global.maxpipes != 0) {
1048 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001049 err_code |= ERR_ALERT;
1050 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001051 }
1052 if (*(args[1]) == 0) {
1053 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001054 err_code |= ERR_ALERT | ERR_FATAL;
1055 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001056 }
1057 global.maxpipes = atol(args[1]);
1058 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001059 else if (!strcmp(args[0], "maxzlibmem")) {
1060 if (*(args[1]) == 0) {
1061 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1062 err_code |= ERR_ALERT | ERR_FATAL;
1063 goto out;
1064 }
William Lallemande3a7d992012-11-20 11:25:20 +01001065 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001066 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001067 else if (!strcmp(args[0], "maxcompcpuusage")) {
1068 if (*(args[1]) == 0) {
1069 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
1072 }
1073 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001074 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001075 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1076 err_code |= ERR_ALERT | ERR_FATAL;
1077 goto out;
1078 }
1079}
1080
Willy Tarreaubaaee002006-06-26 02:48:02 +02001081 else if (!strcmp(args[0], "ulimit-n")) {
1082 if (global.rlimit_nofile != 0) {
1083 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001084 err_code |= ERR_ALERT;
1085 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001086 }
1087 if (*(args[1]) == 0) {
1088 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001089 err_code |= ERR_ALERT | ERR_FATAL;
1090 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091 }
1092 global.rlimit_nofile = atol(args[1]);
1093 }
1094 else if (!strcmp(args[0], "chroot")) {
1095 if (global.chroot != NULL) {
1096 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001097 err_code |= ERR_ALERT;
1098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099 }
1100 if (*(args[1]) == 0) {
1101 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001102 err_code |= ERR_ALERT | ERR_FATAL;
1103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001104 }
1105 global.chroot = strdup(args[1]);
1106 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001107 else if (!strcmp(args[0], "description")) {
1108 int i, len=0;
1109 char *d;
1110
1111 if (!*args[1]) {
1112 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1113 file, linenum, args[0]);
1114 err_code |= ERR_ALERT | ERR_FATAL;
1115 goto out;
1116 }
1117
Willy Tarreau348acfe2014-04-14 15:00:39 +02001118 for (i = 1; *args[i]; i++)
1119 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001120
1121 if (global.desc)
1122 free(global.desc);
1123
1124 global.desc = d = (char *)calloc(1, len);
1125
Willy Tarreau348acfe2014-04-14 15:00:39 +02001126 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1127 for (i = 2; *args[i]; i++)
1128 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001129 }
1130 else if (!strcmp(args[0], "node")) {
1131 int i;
1132 char c;
1133
1134 for (i=0; args[1][i]; i++) {
1135 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001136 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1137 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001138 break;
1139 }
1140
1141 if (!i || args[1][i]) {
1142 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1143 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1144 file, linenum, args[0]);
1145 err_code |= ERR_ALERT | ERR_FATAL;
1146 goto out;
1147 }
1148
1149 if (global.node)
1150 free(global.node);
1151
1152 global.node = strdup(args[1]);
1153 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154 else if (!strcmp(args[0], "pidfile")) {
1155 if (global.pidfile != NULL) {
1156 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001157 err_code |= ERR_ALERT;
1158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001159 }
1160 if (*(args[1]) == 0) {
1161 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001162 err_code |= ERR_ALERT | ERR_FATAL;
1163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001164 }
1165 global.pidfile = strdup(args[1]);
1166 }
Emeric Bruned760922010-10-22 17:59:25 +02001167 else if (!strcmp(args[0], "unix-bind")) {
1168 int cur_arg = 1;
1169 while (*(args[cur_arg])) {
1170 if (!strcmp(args[cur_arg], "prefix")) {
1171 if (global.unix_bind.prefix != NULL) {
1172 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1173 err_code |= ERR_ALERT;
1174 cur_arg += 2;
1175 continue;
1176 }
1177
1178 if (*(args[cur_arg+1]) == 0) {
1179 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1180 err_code |= ERR_ALERT | ERR_FATAL;
1181 goto out;
1182 }
1183 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1184 cur_arg += 2;
1185 continue;
1186 }
1187
1188 if (!strcmp(args[cur_arg], "mode")) {
1189
1190 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1191 cur_arg += 2;
1192 continue;
1193 }
1194
1195 if (!strcmp(args[cur_arg], "uid")) {
1196
1197 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1198 cur_arg += 2;
1199 continue;
1200 }
1201
1202 if (!strcmp(args[cur_arg], "gid")) {
1203
1204 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1205 cur_arg += 2;
1206 continue;
1207 }
1208
1209 if (!strcmp(args[cur_arg], "user")) {
1210 struct passwd *user;
1211
1212 user = getpwnam(args[cur_arg + 1]);
1213 if (!user) {
1214 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1215 file, linenum, args[0], args[cur_arg + 1 ]);
1216 err_code |= ERR_ALERT | ERR_FATAL;
1217 goto out;
1218 }
1219
1220 global.unix_bind.ux.uid = user->pw_uid;
1221 cur_arg += 2;
1222 continue;
1223 }
1224
1225 if (!strcmp(args[cur_arg], "group")) {
1226 struct group *group;
1227
1228 group = getgrnam(args[cur_arg + 1]);
1229 if (!group) {
1230 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1231 file, linenum, args[0], args[cur_arg + 1 ]);
1232 err_code |= ERR_ALERT | ERR_FATAL;
1233 goto out;
1234 }
1235
1236 global.unix_bind.ux.gid = group->gr_gid;
1237 cur_arg += 2;
1238 continue;
1239 }
1240
Willy Tarreaub48f9582011-09-05 01:17:06 +02001241 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001242 file, linenum, args[0]);
1243 err_code |= ERR_ALERT | ERR_FATAL;
1244 goto out;
1245 }
1246 }
William Lallemand0f99e342011-10-12 17:50:54 +02001247 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1248 /* delete previous herited or defined syslog servers */
1249 struct logsrv *back;
1250 struct logsrv *tmp;
1251
1252 if (*(args[1]) != 0) {
1253 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1254 err_code |= ERR_ALERT | ERR_FATAL;
1255 goto out;
1256 }
1257
1258 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1259 LIST_DEL(&tmp->list);
1260 free(tmp);
1261 }
1262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001263 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001264 struct sockaddr_storage *sk;
1265 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001266 struct logsrv *logsrv;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001267 int arg = 0;
1268 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001269
Willy Tarreaubaaee002006-06-26 02:48:02 +02001270 if (*(args[1]) == 0 || *(args[2]) == 0) {
1271 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001272 err_code |= ERR_ALERT | ERR_FATAL;
1273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001274 }
William Lallemand0f99e342011-10-12 17:50:54 +02001275
1276 logsrv = calloc(1, sizeof(struct logsrv));
1277
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001278 /* just after the address, a length may be specified */
1279 if (strcmp(args[arg+2], "len") == 0) {
1280 len = atoi(args[arg+3]);
1281 if (len < 80 || len > 65535) {
1282 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1283 file, linenum, args[arg+3]);
1284 err_code |= ERR_ALERT | ERR_FATAL;
1285 goto out;
1286 }
1287 logsrv->maxlen = len;
1288
1289 /* skip these two args */
1290 arg += 2;
1291 }
1292 else
1293 logsrv->maxlen = MAX_SYSLOG_LEN;
1294
1295 if (logsrv->maxlen > global.max_syslog_len) {
1296 global.max_syslog_len = logsrv->maxlen;
1297 logline = realloc(logline, global.max_syslog_len + 1);
1298 }
1299
1300 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001301 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001302 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001303 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001304 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001305 }
1306
William Lallemand0f99e342011-10-12 17:50:54 +02001307 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001308 if (*(args[arg+3])) {
1309 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001310 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001311 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001312 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001313 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001314 }
1315 }
1316
William Lallemand0f99e342011-10-12 17:50:54 +02001317 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001318 if (*(args[arg+4])) {
1319 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001320 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001321 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001322 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001323 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001324 }
1325 }
1326
Willy Tarreau902636f2013-03-10 19:44:48 +01001327 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001328 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001329 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001330 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001331 free(logsrv);
1332 goto out;
1333 }
1334 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001335
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001336 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001337 if (port1 != port2) {
1338 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1339 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001340 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001341 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001342 goto out;
1343 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001344
William Lallemand0f99e342011-10-12 17:50:54 +02001345 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001346 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001347 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001348 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349
William Lallemand0f99e342011-10-12 17:50:54 +02001350 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001351 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001352 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1353 char *name;
1354 int len;
1355
1356 if (global.log_send_hostname != NULL) {
1357 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1358 err_code |= ERR_ALERT;
1359 goto out;
1360 }
1361
1362 if (*(args[1]))
1363 name = args[1];
1364 else
1365 name = hostname;
1366
1367 len = strlen(name);
1368
1369 /* We'll add a space after the name to respect the log format */
1370 free(global.log_send_hostname);
1371 global.log_send_hostname = malloc(len + 2);
1372 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1373 }
Kevinm48936af2010-12-22 16:08:21 +00001374 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1375 if (*(args[1]) == 0) {
1376 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1377 err_code |= ERR_ALERT | ERR_FATAL;
1378 goto out;
1379 }
1380 free(global.log_tag);
1381 global.log_tag = strdup(args[1]);
1382 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001383 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1384 if (global.spread_checks != 0) {
1385 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001386 err_code |= ERR_ALERT;
1387 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001388 }
1389 if (*(args[1]) == 0) {
1390 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001391 err_code |= ERR_ALERT | ERR_FATAL;
1392 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001393 }
1394 global.spread_checks = atol(args[1]);
1395 if (global.spread_checks < 0 || global.spread_checks > 50) {
1396 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001397 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001398 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001400 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1401 const char *err;
1402 unsigned int val;
1403
1404
1405 if (*(args[1]) == 0) {
1406 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1407 err_code |= ERR_ALERT | ERR_FATAL;
1408 goto out;
1409 }
1410
1411 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1412 if (err) {
1413 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1414 err_code |= ERR_ALERT | ERR_FATAL;
1415 }
1416 global.max_spread_checks = val;
1417 if (global.max_spread_checks < 0) {
1418 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1419 err_code |= ERR_ALERT | ERR_FATAL;
1420 }
1421 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001422 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1423#ifdef USE_CPU_AFFINITY
1424 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001425 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001426 unsigned long cpus = 0;
1427
1428 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001429 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001430 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001431 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001432 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001433 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001434 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001435 proc = atol(args[1]);
1436 if (proc >= 1 && proc <= LONGBITS)
1437 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001438 }
1439
1440 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001441 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",
1442 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001443 err_code |= ERR_ALERT | ERR_FATAL;
1444 goto out;
1445 }
1446
1447 cur_arg = 2;
1448 while (*args[cur_arg]) {
1449 unsigned int low, high;
1450
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001451 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001452 char *dash = strchr(args[cur_arg], '-');
1453
1454 low = high = str2uic(args[cur_arg]);
1455 if (dash)
1456 high = str2uic(dash + 1);
1457
1458 if (high < low) {
1459 unsigned int swap = low;
1460 low = high;
1461 high = swap;
1462 }
1463
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001464 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001465 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001466 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001467 err_code |= ERR_ALERT | ERR_FATAL;
1468 goto out;
1469 }
1470
1471 while (low <= high)
1472 cpus |= 1UL << low++;
1473 }
1474 else {
1475 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1476 file, linenum, args[0], args[cur_arg]);
1477 err_code |= ERR_ALERT | ERR_FATAL;
1478 goto out;
1479 }
1480 cur_arg++;
1481 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001482 for (i = 0; i < LONGBITS; i++)
1483 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001484 global.cpu_map[i] = cpus;
1485#else
1486 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1487 err_code |= ERR_ALERT | ERR_FATAL;
1488 goto out;
1489#endif
1490 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001491 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001492 struct cfg_kw_list *kwl;
1493 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001494 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001495
1496 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1497 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1498 if (kwl->kw[index].section != CFG_GLOBAL)
1499 continue;
1500 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001501 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001502 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001503 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001504 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001505 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001506 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001507 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001508 err_code |= ERR_WARN;
1509 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001510 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001511 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001512 }
1513 }
1514 }
1515
Willy Tarreaubaaee002006-06-26 02:48:02 +02001516 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001517 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001518 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001519
Willy Tarreau058e9072009-07-20 09:30:05 +02001520 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001521 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001522 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523}
1524
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001525void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001526{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001527 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001528 defproxy.mode = PR_MODE_TCP;
1529 defproxy.state = PR_STNEW;
1530 defproxy.maxconn = cfg_maxpconn;
1531 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001532
Simon Horman66183002013-02-23 10:16:43 +09001533 defproxy.defsrv.check.inter = DEF_CHKINTR;
1534 defproxy.defsrv.check.fastinter = 0;
1535 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001536 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1537 defproxy.defsrv.agent.fastinter = 0;
1538 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001539 defproxy.defsrv.check.rise = DEF_RISETIME;
1540 defproxy.defsrv.check.fall = DEF_FALLTIME;
1541 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1542 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001543 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001544 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001545 defproxy.defsrv.maxqueue = 0;
1546 defproxy.defsrv.minconn = 0;
1547 defproxy.defsrv.maxconn = 0;
1548 defproxy.defsrv.slowstart = 0;
1549 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1550 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1551 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001552}
1553
Willy Tarreauade5ec42010-01-28 19:33:49 +01001554
Willy Tarreau63af98d2014-05-18 08:11:41 +02001555/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1556 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1557 * ERR_FATAL in case of error.
1558 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001559static int create_cond_regex_rule(const char *file, int line,
1560 struct proxy *px, int dir, int action, int flags,
1561 const char *cmd, const char *reg, const char *repl,
1562 const char **cond_start)
1563{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001564 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001565 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001566 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001567 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001568 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001569 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001570 int cs;
1571 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001572
1573 if (px == &defproxy) {
1574 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001575 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001576 goto err;
1577 }
1578
1579 if (*reg == 0) {
1580 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001581 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001582 goto err;
1583 }
1584
1585 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001586 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001587
Willy Tarreau5321c422010-01-28 20:35:13 +01001588 if (cond_start &&
1589 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001590 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1591 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1592 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001593 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001594 goto err;
1595 }
1596 }
1597 else if (cond_start && **cond_start) {
1598 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1599 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001600 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001601 goto err;
1602 }
1603
Willy Tarreau63af98d2014-05-18 08:11:41 +02001604 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001605 (dir == SMP_OPT_DIR_REQ) ?
1606 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1607 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1608 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001609
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001610 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001611 if (!preg) {
1612 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001613 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001614 goto err;
1615 }
1616
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001617 cs = !(flags & REG_ICASE);
1618 cap = !(flags & REG_NOSUB);
1619 error = NULL;
1620 if (!regex_comp(reg, preg, cs, cap, &error)) {
1621 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1622 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001623 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001624 goto err;
1625 }
1626
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001627 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001628 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001629 if (repl && err) {
1630 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1631 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001632 ret_code |= ERR_ALERT | ERR_FATAL;
1633 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001634 }
1635
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001636 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001637 ret_code |= ERR_WARN;
1638
1639 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001640
Willy Tarreau63af98d2014-05-18 08:11:41 +02001641 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001642 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001643 err:
1644 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001645 free(errmsg);
1646 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001647}
1648
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001650 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001651 * Returns the error code, 0 if OK, or any combination of :
1652 * - ERR_ABORT: must abort ASAP
1653 * - ERR_FATAL: we can continue parsing but not start the service
1654 * - ERR_WARN: a warning has been emitted
1655 * - ERR_ALERT: an alert has been emitted
1656 * Only the two first ones can stop processing, the two others are just
1657 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001658 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001659int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1660{
1661 static struct peers *curpeers = NULL;
1662 struct peer *newpeer = NULL;
1663 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001664 struct bind_conf *bind_conf;
1665 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001666 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001667 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001668
1669 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001670 if (!*args[1]) {
1671 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001672 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001673 goto out;
1674 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001675
1676 err = invalid_char(args[1]);
1677 if (err) {
1678 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1679 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001680 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001681 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001682 }
1683
1684 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1685 /*
1686 * If there are two proxies with the same name only following
1687 * combinations are allowed:
1688 */
1689 if (strcmp(curpeers->id, args[1]) == 0) {
1690 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1691 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1692 err_code |= ERR_WARN;
1693 }
1694 }
1695
1696 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1697 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1698 err_code |= ERR_ALERT | ERR_ABORT;
1699 goto out;
1700 }
1701
1702 curpeers->next = peers;
1703 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001704 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001705 curpeers->conf.line = linenum;
1706 curpeers->last_change = now.tv_sec;
1707 curpeers->id = strdup(args[1]);
1708 }
1709 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001710 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001711 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001712 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001713
1714 if (!*args[2]) {
1715 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1716 file, linenum, args[0]);
1717 err_code |= ERR_ALERT | ERR_FATAL;
1718 goto out;
1719 }
1720
1721 err = invalid_char(args[1]);
1722 if (err) {
1723 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1724 file, linenum, *err, args[1]);
1725 err_code |= ERR_ALERT | ERR_FATAL;
1726 goto out;
1727 }
1728
1729 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1730 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1731 err_code |= ERR_ALERT | ERR_ABORT;
1732 goto out;
1733 }
1734
1735 /* the peers are linked backwards first */
1736 curpeers->count++;
1737 newpeer->next = curpeers->remote;
1738 curpeers->remote = newpeer;
1739 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001740 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001741 newpeer->conf.line = linenum;
1742
1743 newpeer->last_change = now.tv_sec;
1744 newpeer->id = strdup(args[1]);
1745
Willy Tarreau902636f2013-03-10 19:44:48 +01001746 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001747 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001748 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001749 err_code |= ERR_ALERT | ERR_FATAL;
1750 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001751 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001752
1753 proto = protocol_by_family(sk->ss_family);
1754 if (!proto || !proto->connect) {
1755 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1756 file, linenum, args[0], args[1]);
1757 err_code |= ERR_ALERT | ERR_FATAL;
1758 goto out;
1759 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001760
1761 if (port1 != port2) {
1762 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1763 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
1766 }
1767
Willy Tarreau2aa38802013-02-20 19:20:59 +01001768 if (!port1) {
1769 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1770 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001771 err_code |= ERR_ALERT | ERR_FATAL;
1772 goto out;
1773 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001774
Emeric Brun32da3c42010-09-23 18:39:19 +02001775 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001776 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001777 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001778 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001779
Emeric Brun32da3c42010-09-23 18:39:19 +02001780 if (strcmp(newpeer->id, localpeer) == 0) {
1781 /* Current is local peer, it define a frontend */
1782 newpeer->local = 1;
1783
1784 if (!curpeers->peers_fe) {
1785 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1786 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1787 err_code |= ERR_ALERT | ERR_ABORT;
1788 goto out;
1789 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001790
Willy Tarreau237250c2011-07-29 01:49:03 +02001791 init_new_proxy(curpeers->peers_fe);
1792 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001793
1794 curpeers->peers_fe->last_change = now.tv_sec;
1795 curpeers->peers_fe->id = strdup(args[1]);
1796 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001797 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001798 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1799 curpeers->peers_fe->timeout.connect = 5000;
1800 curpeers->peers_fe->accept = peer_accept;
1801 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001802 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1803 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001804
1805 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1806
Willy Tarreau902636f2013-03-10 19:44:48 +01001807 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1808 if (errmsg && *errmsg) {
1809 indent_msg(&errmsg, 2);
1810 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001811 }
1812 else
1813 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1814 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001815 err_code |= ERR_FATAL;
1816 goto out;
1817 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001818
1819 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001820 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001821 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1822 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1823 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1824 l->accept = session_accept;
1825 l->handler = process_session;
1826 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1827 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1828 global.maxsock += l->maxconn;
1829 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001830 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001831 else {
1832 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1833 file, linenum, args[0], args[1],
1834 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1835 err_code |= ERR_FATAL;
1836 goto out;
1837 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001838 }
1839 } /* neither "peer" nor "peers" */
1840 else if (*args[0] != 0) {
1841 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1842 err_code |= ERR_ALERT | ERR_FATAL;
1843 goto out;
1844 }
1845
1846out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001847 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001848 return err_code;
1849}
1850
Willy Tarreau3842f002009-06-14 11:39:52 +02001851int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001852{
1853 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001854 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001855 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001856 int rc;
1857 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001858 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001859 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001860 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001861 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001862 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001863
Willy Tarreau977b8e42006-12-29 14:19:17 +01001864 if (!strcmp(args[0], "listen"))
1865 rc = PR_CAP_LISTEN;
1866 else if (!strcmp(args[0], "frontend"))
1867 rc = PR_CAP_FE | PR_CAP_RS;
1868 else if (!strcmp(args[0], "backend"))
1869 rc = PR_CAP_BE | PR_CAP_RS;
1870 else if (!strcmp(args[0], "ruleset"))
1871 rc = PR_CAP_RS;
1872 else
1873 rc = PR_CAP_NONE;
1874
1875 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001876 struct ebpt_node *node;
1877
Willy Tarreaubaaee002006-06-26 02:48:02 +02001878 if (!*args[1]) {
1879 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1880 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1881 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001882 err_code |= ERR_ALERT | ERR_ABORT;
1883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001884 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001885
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001886 err = invalid_char(args[1]);
1887 if (err) {
1888 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1889 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001890 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001891 }
1892
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001893 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1894 curproxy = container_of(node, struct proxy, conf.by_name);
1895
1896 if (strcmp(curproxy->id, args[1]) != 0)
1897 break;
1898
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001899 /*
1900 * If there are two proxies with the same name only following
1901 * combinations are allowed:
1902 *
1903 * listen backend frontend ruleset
1904 * listen - - - -
1905 * backend - - OK -
1906 * frontend - OK - -
1907 * ruleset - - - -
1908 */
1909
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001910 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1911 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001912 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1913 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1914 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001915 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001916 }
1917 }
1918
Willy Tarreaubaaee002006-06-26 02:48:02 +02001919 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1920 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001921 err_code |= ERR_ALERT | ERR_ABORT;
1922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001923 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001924
Willy Tarreau97cb7802010-01-03 20:23:58 +01001925 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001926 curproxy->next = proxy;
1927 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001928 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1929 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001930 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001932 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001933 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934
1935 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001936 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001937 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001938
Willy Tarreau4348fad2012-09-20 16:48:07 +02001939 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1940
Willy Tarreau902636f2013-03-10 19:44:48 +01001941 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1942 if (errmsg && *errmsg) {
1943 indent_msg(&errmsg, 2);
1944 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001945 }
1946 else
1947 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1948 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001949 err_code |= ERR_FATAL;
1950 goto out;
1951 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001952
Willy Tarreau4348fad2012-09-20 16:48:07 +02001953 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001954 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001955 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001956 }
1957
1958 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001959 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001960 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001961
Willy Tarreaubaaee002006-06-26 02:48:02 +02001962 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001963 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001964 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001965 curproxy->no_options = defproxy.no_options;
1966 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001967 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001968 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001969 curproxy->except_net = defproxy.except_net;
1970 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001971 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001972 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001974 if (defproxy.fwdfor_hdr_len) {
1975 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1976 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1977 }
1978
Willy Tarreaub86db342009-11-30 11:50:16 +01001979 if (defproxy.orgto_hdr_len) {
1980 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1981 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1982 }
1983
Mark Lamourinec2247f02012-01-04 13:02:01 -05001984 if (defproxy.server_id_hdr_len) {
1985 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1986 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1987 }
1988
Willy Tarreau977b8e42006-12-29 14:19:17 +01001989 if (curproxy->cap & PR_CAP_FE) {
1990 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001991 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001992 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001993
1994 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001995 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1996 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001997
1998 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1999 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002000
Willy Tarreau977b8e42006-12-29 14:19:17 +01002001 if (curproxy->cap & PR_CAP_BE) {
2002 curproxy->fullconn = defproxy.fullconn;
2003 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002004 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002005
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002006 if (defproxy.check_req) {
2007 curproxy->check_req = calloc(1, defproxy.check_len);
2008 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2009 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002010 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002011
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002012 if (defproxy.expect_str) {
2013 curproxy->expect_str = strdup(defproxy.expect_str);
2014 if (defproxy.expect_regex) {
2015 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002016 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2017 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002018 }
2019 }
2020
Willy Tarreau67402132012-05-31 20:40:20 +02002021 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002022 if (defproxy.cookie_name)
2023 curproxy->cookie_name = strdup(defproxy.cookie_name);
2024 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002025 if (defproxy.cookie_domain)
2026 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002027
Willy Tarreau31936852010-10-06 16:59:56 +02002028 if (defproxy.cookie_maxidle)
2029 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2030
2031 if (defproxy.cookie_maxlife)
2032 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2033
Emeric Brun647caf12009-06-30 17:57:00 +02002034 if (defproxy.rdp_cookie_name)
2035 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2036 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2037
Willy Tarreau01732802007-11-01 22:48:15 +01002038 if (defproxy.url_param_name)
2039 curproxy->url_param_name = strdup(defproxy.url_param_name);
2040 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002041
Benoitaffb4812009-03-25 13:02:10 +01002042 if (defproxy.hh_name)
2043 curproxy->hh_name = strdup(defproxy.hh_name);
2044 curproxy->hh_len = defproxy.hh_len;
2045 curproxy->hh_match_domain = defproxy.hh_match_domain;
2046
Willy Tarreauef9a3602012-12-08 22:29:20 +01002047 if (defproxy.conn_src.iface_name)
2048 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2049 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002050 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002051#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002052 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002053#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002054 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002055
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002056 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002057 if (defproxy.capture_name)
2058 curproxy->capture_name = strdup(defproxy.capture_name);
2059 curproxy->capture_namelen = defproxy.capture_namelen;
2060 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002061 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002062
Willy Tarreau977b8e42006-12-29 14:19:17 +01002063 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002064 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002065 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002066 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002067 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002068 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002069 curproxy->mon_net = defproxy.mon_net;
2070 curproxy->mon_mask = defproxy.mon_mask;
2071 if (defproxy.monitor_uri)
2072 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2073 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002074 if (defproxy.defbe.name)
2075 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002076
2077 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002078 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2079 if (curproxy->conf.logformat_string &&
2080 curproxy->conf.logformat_string != default_http_log_format &&
2081 curproxy->conf.logformat_string != default_tcp_log_format &&
2082 curproxy->conf.logformat_string != clf_http_log_format)
2083 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2084
2085 if (defproxy.conf.lfs_file) {
2086 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2087 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2088 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002089 }
2090
2091 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002092 curproxy->timeout.connect = defproxy.timeout.connect;
2093 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002094 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002095 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002096 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002097 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002098 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002099 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002100 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002101 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002102 }
2103
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002105 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002106
2107 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002108 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002109 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002110 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002111 LIST_INIT(&node->list);
2112 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2113 }
2114
Willy Tarreau62a61232013-04-12 18:13:46 +02002115 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2116 if (curproxy->conf.uniqueid_format_string)
2117 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2118
2119 if (defproxy.conf.uif_file) {
2120 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2121 curproxy->conf.uif_line = defproxy.conf.uif_line;
2122 }
William Lallemanda73203e2012-03-12 12:48:57 +01002123
2124 /* copy default header unique id */
2125 if (defproxy.header_unique_id)
2126 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2127
William Lallemand82fe75c2012-10-23 10:25:10 +02002128 /* default compression options */
2129 if (defproxy.comp != NULL) {
2130 curproxy->comp = calloc(1, sizeof(struct comp));
2131 curproxy->comp->algos = defproxy.comp->algos;
2132 curproxy->comp->types = defproxy.comp->types;
2133 }
2134
Willy Tarreaubaaee002006-06-26 02:48:02 +02002135 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002136 curproxy->conf.used_listener_id = EB_ROOT;
2137 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002138
Willy Tarreau93893792009-07-23 13:19:11 +02002139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002140 }
2141 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2142 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002143 /* FIXME-20070101: we should do this too at the end of the
2144 * config parsing to free all default values.
2145 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002146 free(defproxy.check_req);
2147 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002148 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002149 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002150 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002151 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002152 free(defproxy.capture_name);
2153 free(defproxy.monitor_uri);
2154 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002155 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002156 free(defproxy.fwdfor_hdr_name);
2157 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002158 free(defproxy.orgto_hdr_name);
2159 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002160 free(defproxy.server_id_hdr_name);
2161 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002162 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002163 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002164 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002165 free(defproxy.expect_regex);
2166 defproxy.expect_regex = NULL;
2167 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002168
Willy Tarreau62a61232013-04-12 18:13:46 +02002169 if (defproxy.conf.logformat_string != default_http_log_format &&
2170 defproxy.conf.logformat_string != default_tcp_log_format &&
2171 defproxy.conf.logformat_string != clf_http_log_format)
2172 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002173
Willy Tarreau62a61232013-04-12 18:13:46 +02002174 free(defproxy.conf.uniqueid_format_string);
2175 free(defproxy.conf.lfs_file);
2176 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002177
Willy Tarreaua534fea2008-08-03 12:19:50 +02002178 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002179 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002180
Willy Tarreaubaaee002006-06-26 02:48:02 +02002181 /* we cannot free uri_auth because it might already be used */
2182 init_default_instance();
2183 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002184 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2185 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002186 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002188 }
2189 else if (curproxy == NULL) {
2190 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002191 err_code |= ERR_ALERT | ERR_FATAL;
2192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002193 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002194
2195 /* update the current file and line being parsed */
2196 curproxy->conf.args.file = curproxy->conf.file;
2197 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002198
2199 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002200 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2201 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2202 if (err_code & ERR_FATAL)
2203 goto out;
2204 }
2205 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002206 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002207 int cur_arg;
2208
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 if (curproxy == &defproxy) {
2210 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002211 err_code |= ERR_ALERT | ERR_FATAL;
2212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002213 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002214 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002215 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002216
Willy Tarreau24709282013-03-10 21:32:12 +01002217 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002218 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002219 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002220 err_code |= ERR_ALERT | ERR_FATAL;
2221 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002222 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002223
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002224 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002225
2226 /* use default settings for unix sockets */
2227 bind_conf->ux.uid = global.unix_bind.ux.uid;
2228 bind_conf->ux.gid = global.unix_bind.ux.gid;
2229 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002230
2231 /* NOTE: the following line might create several listeners if there
2232 * are comma-separated IPs or port ranges. So all further processing
2233 * will have to be applied to all listeners created after last_listen.
2234 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002235 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2236 if (errmsg && *errmsg) {
2237 indent_msg(&errmsg, 2);
2238 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002239 }
2240 else
2241 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2242 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
2245 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002246
Willy Tarreau4348fad2012-09-20 16:48:07 +02002247 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2248 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002249 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002250 }
2251
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002252 cur_arg = 2;
2253 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002254 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002255 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002256 char *err;
2257
Willy Tarreau26982662012-09-12 23:17:10 +02002258 kw = bind_find_kw(args[cur_arg]);
2259 if (kw) {
2260 char *err = NULL;
2261 int code;
2262
2263 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002264 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2265 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002266 cur_arg += 1 + kw->skip ;
2267 err_code |= ERR_ALERT | ERR_FATAL;
2268 goto out;
2269 }
2270
Willy Tarreau4348fad2012-09-20 16:48:07 +02002271 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002272 err_code |= code;
2273
2274 if (code) {
2275 if (err && *err) {
2276 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002277 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002278 }
2279 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002280 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2281 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002282 if (code & ERR_FATAL) {
2283 free(err);
2284 cur_arg += 1 + kw->skip;
2285 goto out;
2286 }
2287 }
2288 free(err);
2289 cur_arg += 1 + kw->skip;
2290 continue;
2291 }
2292
Willy Tarreau8638f482012-09-18 18:01:17 +02002293 err = NULL;
2294 if (!bind_dumped) {
2295 bind_dump_kws(&err);
2296 indent_msg(&err, 4);
2297 bind_dumped = 1;
2298 }
2299
2300 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2301 file, linenum, args[0], args[1], args[cur_arg],
2302 err ? " Registered keywords :" : "", err ? err : "");
2303 free(err);
2304
Willy Tarreau93893792009-07-23 13:19:11 +02002305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002307 }
Willy Tarreau93893792009-07-23 13:19:11 +02002308 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309 }
2310 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002311 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002312 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2313 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002314 err_code |= ERR_ALERT | ERR_FATAL;
2315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002316 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002317 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002318 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002319
Willy Tarreaubaaee002006-06-26 02:48:02 +02002320 /* flush useless bits */
2321 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002323 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002324 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002325 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002326 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002327
Willy Tarreau1c47f852006-07-09 08:22:27 +02002328 if (!*args[1]) {
2329 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2330 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002331 err_code |= ERR_ALERT | ERR_FATAL;
2332 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002333 }
2334
Willy Tarreaua534fea2008-08-03 12:19:50 +02002335 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002336 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002337 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002338 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002339 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2340
Willy Tarreau93893792009-07-23 13:19:11 +02002341 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002342 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002343 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2344 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2345 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2346 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2347 else {
2348 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002349 err_code |= ERR_ALERT | ERR_FATAL;
2350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 }
2352 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002353 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002354 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002355
2356 if (curproxy == &defproxy) {
2357 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2358 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_ALERT | ERR_FATAL;
2360 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002361 }
2362
2363 if (!*args[1]) {
2364 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2365 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002368 }
2369
2370 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002371 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002372
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002373 if (curproxy->uuid <= 0) {
2374 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002375 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002376 err_code |= ERR_ALERT | ERR_FATAL;
2377 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002378 }
2379
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002380 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2381 if (node) {
2382 struct proxy *target = container_of(node, struct proxy, conf.id);
2383 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2384 file, linenum, proxy_type_str(curproxy), curproxy->id,
2385 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2386 err_code |= ERR_ALERT | ERR_FATAL;
2387 goto out;
2388 }
2389 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002390 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002391 else if (!strcmp(args[0], "description")) {
2392 int i, len=0;
2393 char *d;
2394
Cyril Bonté99ed3272010-01-24 23:29:44 +01002395 if (curproxy == &defproxy) {
2396 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2397 file, linenum, args[0]);
2398 err_code |= ERR_ALERT | ERR_FATAL;
2399 goto out;
2400 }
2401
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002402 if (!*args[1]) {
2403 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2404 file, linenum, args[0]);
2405 return -1;
2406 }
2407
Willy Tarreau348acfe2014-04-14 15:00:39 +02002408 for (i = 1; *args[i]; i++)
2409 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002410
2411 d = (char *)calloc(1, len);
2412 curproxy->desc = d;
2413
Willy Tarreau348acfe2014-04-14 15:00:39 +02002414 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2415 for (i = 2; *args[i]; i++)
2416 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002417
2418 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002419 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2420 curproxy->state = PR_STSTOPPED;
2421 }
2422 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2423 curproxy->state = PR_STNEW;
2424 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002425 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2426 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002427 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002428
2429 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002430 unsigned int low, high;
2431
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002432 if (strcmp(args[cur_arg], "all") == 0) {
2433 set = 0;
2434 break;
2435 }
2436 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002437 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002438 }
2439 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002440 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002441 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002442 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002443 char *dash = strchr(args[cur_arg], '-');
2444
2445 low = high = str2uic(args[cur_arg]);
2446 if (dash)
2447 high = str2uic(dash + 1);
2448
2449 if (high < low) {
2450 unsigned int swap = low;
2451 low = high;
2452 high = swap;
2453 }
2454
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002455 if (low < 1 || high > LONGBITS) {
2456 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2457 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002458 err_code |= ERR_ALERT | ERR_FATAL;
2459 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002460 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002461 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002462 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002463 }
2464 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002465 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2466 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002467 err_code |= ERR_ALERT | ERR_FATAL;
2468 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002469 }
2470 cur_arg++;
2471 }
2472 curproxy->bind_proc = set;
2473 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002474 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002475 if (curproxy == &defproxy) {
2476 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002479 }
2480
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002481 err = invalid_char(args[1]);
2482 if (err) {
2483 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2484 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002485 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002486 }
2487
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002488 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002489 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2490 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002491 err_code |= ERR_ALERT | ERR_FATAL;
2492 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002493 }
2494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2496 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497
Willy Tarreau977b8e42006-12-29 14:19:17 +01002498 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002499 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002500
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 if (*(args[1]) == 0) {
2502 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2503 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002506 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002507
Willy Tarreau67402132012-05-31 20:40:20 +02002508 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002509 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002510 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002511 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 curproxy->cookie_name = strdup(args[1]);
2513 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002514
Willy Tarreaubaaee002006-06-26 02:48:02 +02002515 cur_arg = 2;
2516 while (*(args[cur_arg])) {
2517 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002518 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002519 }
2520 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002521 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002522 }
2523 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002524 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002525 }
2526 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002527 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002528 }
2529 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002530 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002532 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002533 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002534 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002535 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002536 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002537 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002538 else if (!strcmp(args[cur_arg], "httponly")) {
2539 curproxy->ck_opts |= PR_CK_HTTPONLY;
2540 }
2541 else if (!strcmp(args[cur_arg], "secure")) {
2542 curproxy->ck_opts |= PR_CK_SECURE;
2543 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002544 else if (!strcmp(args[cur_arg], "domain")) {
2545 if (!*args[cur_arg + 1]) {
2546 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2547 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002548 err_code |= ERR_ALERT | ERR_FATAL;
2549 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002550 }
2551
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002552 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002553 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002554 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2555 " dots nor does not start with a dot."
2556 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002557 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002558 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002559 }
2560
2561 err = invalid_domainchar(args[cur_arg + 1]);
2562 if (err) {
2563 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2564 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002565 err_code |= ERR_ALERT | ERR_FATAL;
2566 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002567 }
2568
Willy Tarreau68a897b2009-12-03 23:28:34 +01002569 if (!curproxy->cookie_domain) {
2570 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2571 } else {
2572 /* one domain was already specified, add another one by
2573 * building the string which will be returned along with
2574 * the cookie.
2575 */
2576 char *new_ptr;
2577 int new_len = strlen(curproxy->cookie_domain) +
2578 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2579 new_ptr = malloc(new_len);
2580 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2581 free(curproxy->cookie_domain);
2582 curproxy->cookie_domain = new_ptr;
2583 }
Willy Tarreau31936852010-10-06 16:59:56 +02002584 cur_arg++;
2585 }
2586 else if (!strcmp(args[cur_arg], "maxidle")) {
2587 unsigned int maxidle;
2588 const char *res;
2589
2590 if (!*args[cur_arg + 1]) {
2591 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2592 file, linenum, args[cur_arg]);
2593 err_code |= ERR_ALERT | ERR_FATAL;
2594 goto out;
2595 }
2596
2597 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2598 if (res) {
2599 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2600 file, linenum, *res, args[cur_arg]);
2601 err_code |= ERR_ALERT | ERR_FATAL;
2602 goto out;
2603 }
2604 curproxy->cookie_maxidle = maxidle;
2605 cur_arg++;
2606 }
2607 else if (!strcmp(args[cur_arg], "maxlife")) {
2608 unsigned int maxlife;
2609 const char *res;
2610
2611 if (!*args[cur_arg + 1]) {
2612 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2613 file, linenum, args[cur_arg]);
2614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
2616 }
2617
2618 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2619 if (res) {
2620 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2621 file, linenum, *res, args[cur_arg]);
2622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
2624 }
2625 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002626 cur_arg++;
2627 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002628 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002629 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 +02002630 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002631 err_code |= ERR_ALERT | ERR_FATAL;
2632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002633 }
2634 cur_arg++;
2635 }
Willy Tarreau67402132012-05-31 20:40:20 +02002636 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002637 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2638 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002639 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002640 }
2641
Willy Tarreau67402132012-05-31 20:40:20 +02002642 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2644 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002645 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002646 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002647
Willy Tarreau67402132012-05-31 20:40:20 +02002648 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002649 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2650 file, linenum);
2651 err_code |= ERR_ALERT | ERR_FATAL;
2652 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002653 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002654 else if (!strcmp(args[0], "persist")) { /* persist */
2655 if (*(args[1]) == 0) {
2656 Alert("parsing [%s:%d] : missing persist method.\n",
2657 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002658 err_code |= ERR_ALERT | ERR_FATAL;
2659 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002660 }
2661
2662 if (!strncmp(args[1], "rdp-cookie", 10)) {
2663 curproxy->options2 |= PR_O2_RDPC_PRST;
2664
Emeric Brunb982a3d2010-01-04 15:45:53 +01002665 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002666 const char *beg, *end;
2667
2668 beg = args[1] + 11;
2669 end = strchr(beg, ')');
2670
2671 if (!end || end == beg) {
2672 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2673 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002674 err_code |= ERR_ALERT | ERR_FATAL;
2675 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002676 }
2677
2678 free(curproxy->rdp_cookie_name);
2679 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2680 curproxy->rdp_cookie_len = end-beg;
2681 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002682 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002683 free(curproxy->rdp_cookie_name);
2684 curproxy->rdp_cookie_name = strdup("msts");
2685 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2686 }
2687 else { /* syntax */
2688 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2689 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002690 err_code |= ERR_ALERT | ERR_FATAL;
2691 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002692 }
2693 }
2694 else {
2695 Alert("parsing [%s:%d] : unknown persist method.\n",
2696 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002699 }
2700 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002701 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002702 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002703
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002704 if (curproxy == &defproxy) {
2705 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2706 err_code |= ERR_ALERT | ERR_FATAL;
2707 goto out;
2708 }
2709
Willy Tarreau977b8e42006-12-29 14:19:17 +01002710 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002711 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002712
Willy Tarreaubaaee002006-06-26 02:48:02 +02002713 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002714 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002715 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002716 err_code |= ERR_ALERT | ERR_FATAL;
2717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002718 }
2719 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002720 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002721 curproxy->appsession_name = strdup(args[1]);
2722 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2723 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002724 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2725 if (err) {
2726 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2727 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002728 err_code |= ERR_ALERT | ERR_FATAL;
2729 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002730 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002731 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002732
Willy Tarreau51041c72007-09-09 21:56:53 +02002733 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2734 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002735 err_code |= ERR_ALERT | ERR_ABORT;
2736 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002737 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002738
2739 cur_arg = 6;
2740 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002741 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2742 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002743 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002744 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002745 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002746 } else if (!strcmp(args[cur_arg], "prefix")) {
2747 curproxy->options2 |= PR_O2_AS_PFX;
2748 } else if (!strcmp(args[cur_arg], "mode")) {
2749 if (!*args[cur_arg + 1]) {
2750 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2751 file, linenum, args[0], args[cur_arg]);
2752 err_code |= ERR_ALERT | ERR_FATAL;
2753 goto out;
2754 }
2755
2756 cur_arg++;
2757 if (!strcmp(args[cur_arg], "query-string")) {
2758 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2759 curproxy->options2 |= PR_O2_AS_M_QS;
2760 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2761 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2762 curproxy->options2 |= PR_O2_AS_M_PP;
2763 } else {
2764 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2765 err_code |= ERR_ALERT | ERR_FATAL;
2766 goto out;
2767 }
2768 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002769 cur_arg++;
2770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002771 } /* Url App Session */
2772 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002773 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002774 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002775
Willy Tarreaubaaee002006-06-26 02:48:02 +02002776 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002777 if (curproxy == &defproxy) {
2778 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2779 err_code |= ERR_ALERT | ERR_FATAL;
2780 goto out;
2781 }
2782
Willy Tarreaubaaee002006-06-26 02:48:02 +02002783 if (*(args[4]) == 0) {
2784 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2785 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002786 err_code |= ERR_ALERT | ERR_FATAL;
2787 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002788 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002789 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002790 curproxy->capture_name = strdup(args[2]);
2791 curproxy->capture_namelen = strlen(curproxy->capture_name);
2792 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002793 curproxy->to_log |= LW_COOKIE;
2794 }
2795 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2796 struct cap_hdr *hdr;
2797
2798 if (curproxy == &defproxy) {
2799 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 +02002800 err_code |= ERR_ALERT | ERR_FATAL;
2801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002802 }
2803
2804 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2805 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2806 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002807 err_code |= ERR_ALERT | ERR_FATAL;
2808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002809 }
2810
2811 hdr = calloc(sizeof(struct cap_hdr), 1);
2812 hdr->next = curproxy->req_cap;
2813 hdr->name = strdup(args[3]);
2814 hdr->namelen = strlen(args[3]);
2815 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002816 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002817 hdr->index = curproxy->nb_req_cap++;
2818 curproxy->req_cap = hdr;
2819 curproxy->to_log |= LW_REQHDR;
2820 }
2821 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2822 struct cap_hdr *hdr;
2823
2824 if (curproxy == &defproxy) {
2825 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 +02002826 err_code |= ERR_ALERT | ERR_FATAL;
2827 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002828 }
2829
2830 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2831 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2832 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002835 }
2836 hdr = calloc(sizeof(struct cap_hdr), 1);
2837 hdr->next = curproxy->rsp_cap;
2838 hdr->name = strdup(args[3]);
2839 hdr->namelen = strlen(args[3]);
2840 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002841 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002842 hdr->index = curproxy->nb_rsp_cap++;
2843 curproxy->rsp_cap = hdr;
2844 curproxy->to_log |= LW_RSPHDR;
2845 }
2846 else {
2847 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2848 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851 }
2852 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002853 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002854 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002855 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002856
Willy Tarreaubaaee002006-06-26 02:48:02 +02002857 if (*(args[1]) == 0) {
2858 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2859 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002860 err_code |= ERR_ALERT | ERR_FATAL;
2861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002862 }
2863 curproxy->conn_retries = atol(args[1]);
2864 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002865 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002866 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002867
2868 if (curproxy == &defproxy) {
2869 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2870 err_code |= ERR_ALERT | ERR_FATAL;
2871 goto out;
2872 }
2873
Willy Tarreau20b0de52012-12-24 15:45:22 +01002874 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2875 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2876 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2877 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002878 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002879 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2880 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 +01002881 file, linenum, args[0]);
2882 err_code |= ERR_WARN;
2883 }
2884
Willy Tarreauff011f22011-01-06 17:51:27 +01002885 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002886
Willy Tarreauff011f22011-01-06 17:51:27 +01002887 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002888 err_code |= ERR_ALERT | ERR_ABORT;
2889 goto out;
2890 }
2891
Willy Tarreau5002f572014-04-23 01:32:02 +02002892 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002893 err_code |= warnif_cond_conflicts(rule->cond,
2894 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2895 file, linenum);
2896
Willy Tarreauff011f22011-01-06 17:51:27 +01002897 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002898 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002899 else if (!strcmp(args[0], "http-response")) { /* response access control */
2900 struct http_res_rule *rule;
2901
2902 if (curproxy == &defproxy) {
2903 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2904 err_code |= ERR_ALERT | ERR_FATAL;
2905 goto out;
2906 }
2907
2908 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2909 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2910 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2911 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2912 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2913 file, linenum, args[0]);
2914 err_code |= ERR_WARN;
2915 }
2916
2917 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2918
2919 if (!rule) {
2920 err_code |= ERR_ALERT | ERR_ABORT;
2921 goto out;
2922 }
2923
2924 err_code |= warnif_cond_conflicts(rule->cond,
2925 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2926 file, linenum);
2927
2928 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2929 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002930 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2931 /* set the header name and length into the proxy structure */
2932 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2933 err_code |= ERR_WARN;
2934
2935 if (!*args[1]) {
2936 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2937 file, linenum, args[0]);
2938 err_code |= ERR_ALERT | ERR_FATAL;
2939 goto out;
2940 }
2941
2942 /* set the desired header name */
2943 free(curproxy->server_id_hdr_name);
2944 curproxy->server_id_hdr_name = strdup(args[1]);
2945 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2946 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002947 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002948 struct http_req_rule *rule;
2949
Willy Tarreaub099aca2008-10-12 17:26:37 +02002950 if (curproxy == &defproxy) {
2951 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002952 err_code |= ERR_ALERT | ERR_FATAL;
2953 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002954 }
2955
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002956 /* emulate "block" using "http-request block". Since these rules are supposed to
2957 * be processed before all http-request rules, we put them into their own list
2958 * and will insert them at the end.
2959 */
2960 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
2961 if (!rule) {
2962 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02002963 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002964 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002965 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
2966 err_code |= warnif_cond_conflicts(rule->cond,
2967 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2968 file, linenum);
2969 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02002970
2971 if (!already_warned(WARN_BLOCK_DEPRECATED))
2972 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]);
2973
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002974 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002975 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002976 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002977
Cyril Bonté99ed3272010-01-24 23:29:44 +01002978 if (curproxy == &defproxy) {
2979 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2980 err_code |= ERR_ALERT | ERR_FATAL;
2981 goto out;
2982 }
2983
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002984 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002985 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2986 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002989 }
2990
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002991 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02002992 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002993 err_code |= warnif_cond_conflicts(rule->cond,
2994 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2995 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002996 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002997 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002998 struct switching_rule *rule;
2999
Willy Tarreaub099aca2008-10-12 17:26:37 +02003000 if (curproxy == &defproxy) {
3001 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003002 err_code |= ERR_ALERT | ERR_FATAL;
3003 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003004 }
3005
Willy Tarreau55ea7572007-06-17 19:56:27 +02003006 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003007 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003008
3009 if (*(args[1]) == 0) {
3010 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003013 }
3014
Willy Tarreauf51658d2014-04-23 01:21:56 +02003015 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3016 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3017 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3018 file, linenum, errmsg);
3019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
3021 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003022
Willy Tarreauf51658d2014-04-23 01:21:56 +02003023 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003024 }
3025
3026 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3027 rule->cond = cond;
3028 rule->be.name = strdup(args[1]);
3029 LIST_INIT(&rule->list);
3030 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3031 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003032 else if (strcmp(args[0], "use-server") == 0) {
3033 struct server_rule *rule;
3034
3035 if (curproxy == &defproxy) {
3036 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3037 err_code |= ERR_ALERT | ERR_FATAL;
3038 goto out;
3039 }
3040
3041 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3042 err_code |= ERR_WARN;
3043
3044 if (*(args[1]) == 0) {
3045 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3046 err_code |= ERR_ALERT | ERR_FATAL;
3047 goto out;
3048 }
3049
3050 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3051 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3052 file, linenum, args[0]);
3053 err_code |= ERR_ALERT | ERR_FATAL;
3054 goto out;
3055 }
3056
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003057 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3058 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3059 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003060 err_code |= ERR_ALERT | ERR_FATAL;
3061 goto out;
3062 }
3063
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003064 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003065
3066 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3067 rule->cond = cond;
3068 rule->srv.name = strdup(args[1]);
3069 LIST_INIT(&rule->list);
3070 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3071 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3072 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003073 else if ((!strcmp(args[0], "force-persist")) ||
3074 (!strcmp(args[0], "ignore-persist"))) {
3075 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003076
3077 if (curproxy == &defproxy) {
3078 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
3081 }
3082
3083 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3084 err_code |= ERR_WARN;
3085
Willy Tarreauef6494c2010-01-28 17:12:36 +01003086 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003087 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3088 file, linenum, args[0]);
3089 err_code |= ERR_ALERT | ERR_FATAL;
3090 goto out;
3091 }
3092
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003093 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3094 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3095 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003096 err_code |= ERR_ALERT | ERR_FATAL;
3097 goto out;
3098 }
3099
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003100 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3101 * where force-persist is applied.
3102 */
3103 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003104
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003105 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003106 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003107 if (!strcmp(args[0], "force-persist")) {
3108 rule->type = PERSIST_TYPE_FORCE;
3109 } else {
3110 rule->type = PERSIST_TYPE_IGNORE;
3111 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003112 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003113 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003114 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003115 else if (!strcmp(args[0], "stick-table")) {
3116 int myidx = 1;
3117
Emeric Brun32da3c42010-09-23 18:39:19 +02003118 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003119 curproxy->table.type = (unsigned int)-1;
3120 while (*args[myidx]) {
3121 const char *err;
3122
3123 if (strcmp(args[myidx], "size") == 0) {
3124 myidx++;
3125 if (!*(args[myidx])) {
3126 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3127 file, linenum, args[myidx-1]);
3128 err_code |= ERR_ALERT | ERR_FATAL;
3129 goto out;
3130 }
3131 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3132 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3133 file, linenum, *err, args[myidx-1]);
3134 err_code |= ERR_ALERT | ERR_FATAL;
3135 goto out;
3136 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003137 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003138 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003139 else if (strcmp(args[myidx], "peers") == 0) {
3140 myidx++;
Godbach50523162013-12-11 19:48:57 +08003141 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003142 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3143 file, linenum, args[myidx-1]);
3144 err_code |= ERR_ALERT | ERR_FATAL;
3145 goto out;
Godbach50523162013-12-11 19:48:57 +08003146 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003147 curproxy->table.peers.name = strdup(args[myidx++]);
3148 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003149 else if (strcmp(args[myidx], "expire") == 0) {
3150 myidx++;
3151 if (!*(args[myidx])) {
3152 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3153 file, linenum, args[myidx-1]);
3154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
3156 }
3157 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3158 if (err) {
3159 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3160 file, linenum, *err, args[myidx-1]);
3161 err_code |= ERR_ALERT | ERR_FATAL;
3162 goto out;
3163 }
3164 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003165 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003166 }
3167 else if (strcmp(args[myidx], "nopurge") == 0) {
3168 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003169 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003170 }
3171 else if (strcmp(args[myidx], "type") == 0) {
3172 myidx++;
3173 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3174 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3175 file, linenum, args[myidx]);
3176 err_code |= ERR_ALERT | ERR_FATAL;
3177 goto out;
3178 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003179 /* myidx already points to next arg */
3180 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003181 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003182 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003183 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003184
3185 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003186 nw = args[myidx];
3187 while (*nw) {
3188 /* the "store" keyword supports a comma-separated list */
3189 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003190 sa = NULL; /* store arg */
3191 while (*nw && *nw != ',') {
3192 if (*nw == '(') {
3193 *nw = 0;
3194 sa = ++nw;
3195 while (*nw != ')') {
3196 if (!*nw) {
3197 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3198 file, linenum, args[0], cw);
3199 err_code |= ERR_ALERT | ERR_FATAL;
3200 goto out;
3201 }
3202 nw++;
3203 }
3204 *nw = '\0';
3205 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003206 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003207 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003208 if (*nw)
3209 *nw++ = '\0';
3210 type = stktable_get_data_type(cw);
3211 if (type < 0) {
3212 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3213 file, linenum, args[0], cw);
3214 err_code |= ERR_ALERT | ERR_FATAL;
3215 goto out;
3216 }
Willy Tarreauac782882010-06-20 10:41:54 +02003217
3218 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3219 switch (err) {
3220 case PE_NONE: break;
3221 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003222 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3223 file, linenum, args[0], cw);
3224 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003225 break;
3226
3227 case PE_ARG_MISSING:
3228 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3229 file, linenum, args[0], cw);
3230 err_code |= ERR_ALERT | ERR_FATAL;
3231 goto out;
3232
3233 case PE_ARG_NOT_USED:
3234 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3235 file, linenum, args[0], cw);
3236 err_code |= ERR_ALERT | ERR_FATAL;
3237 goto out;
3238
3239 default:
3240 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3241 file, linenum, args[0], cw);
3242 err_code |= ERR_ALERT | ERR_FATAL;
3243 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003244 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003245 }
3246 myidx++;
3247 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003248 else {
3249 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3250 file, linenum, args[myidx]);
3251 err_code |= ERR_ALERT | ERR_FATAL;
3252 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003253 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003254 }
3255
3256 if (!curproxy->table.size) {
3257 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3258 file, linenum);
3259 err_code |= ERR_ALERT | ERR_FATAL;
3260 goto out;
3261 }
3262
3263 if (curproxy->table.type == (unsigned int)-1) {
3264 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3265 file, linenum);
3266 err_code |= ERR_ALERT | ERR_FATAL;
3267 goto out;
3268 }
3269 }
3270 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003271 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003272 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003273 int myidx = 0;
3274 const char *name = NULL;
3275 int flags;
3276
3277 if (curproxy == &defproxy) {
3278 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3279 err_code |= ERR_ALERT | ERR_FATAL;
3280 goto out;
3281 }
3282
3283 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3284 err_code |= ERR_WARN;
3285 goto out;
3286 }
3287
3288 myidx++;
3289 if ((strcmp(args[myidx], "store") == 0) ||
3290 (strcmp(args[myidx], "store-request") == 0)) {
3291 myidx++;
3292 flags = STK_IS_STORE;
3293 }
3294 else if (strcmp(args[myidx], "store-response") == 0) {
3295 myidx++;
3296 flags = STK_IS_STORE | STK_ON_RSP;
3297 }
3298 else if (strcmp(args[myidx], "match") == 0) {
3299 myidx++;
3300 flags = STK_IS_MATCH;
3301 }
3302 else if (strcmp(args[myidx], "on") == 0) {
3303 myidx++;
3304 flags = STK_IS_MATCH | STK_IS_STORE;
3305 }
3306 else {
3307 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3308 err_code |= ERR_ALERT | ERR_FATAL;
3309 goto out;
3310 }
3311
3312 if (*(args[myidx]) == 0) {
3313 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3314 err_code |= ERR_ALERT | ERR_FATAL;
3315 goto out;
3316 }
3317
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003318 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003319 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003320 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003321 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003322 err_code |= ERR_ALERT | ERR_FATAL;
3323 goto out;
3324 }
3325
3326 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003327 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3328 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3329 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003330 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003331 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003332 goto out;
3333 }
3334 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003335 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3336 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3337 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003338 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003339 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003340 goto out;
3341 }
3342 }
3343
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003344 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003345 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003346
Emeric Brunb982a3d2010-01-04 15:45:53 +01003347 if (strcmp(args[myidx], "table") == 0) {
3348 myidx++;
3349 name = args[myidx++];
3350 }
3351
Willy Tarreauef6494c2010-01-28 17:12:36 +01003352 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003353 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3354 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3355 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003356 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003357 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003358 goto out;
3359 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003360 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003361 else if (*(args[myidx])) {
3362 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3363 file, linenum, args[0], args[myidx]);
3364 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003365 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003366 goto out;
3367 }
Emeric Brun97679e72010-09-23 17:56:44 +02003368 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003369 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003370 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003371 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003372
Emeric Brunb982a3d2010-01-04 15:45:53 +01003373 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3374 rule->cond = cond;
3375 rule->expr = expr;
3376 rule->flags = flags;
3377 rule->table.name = name ? strdup(name) : NULL;
3378 LIST_INIT(&rule->list);
3379 if (flags & STK_ON_RSP)
3380 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3381 else
3382 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3383 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 else if (!strcmp(args[0], "stats")) {
3385 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3386 curproxy->uri_auth = NULL; /* we must detach from the default config */
3387
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003388 if (!*args[1]) {
3389 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003390 } else if (!strcmp(args[1], "admin")) {
3391 struct stats_admin_rule *rule;
3392
3393 if (curproxy == &defproxy) {
3394 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3395 err_code |= ERR_ALERT | ERR_FATAL;
3396 goto out;
3397 }
3398
3399 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3400 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3401 err_code |= ERR_ALERT | ERR_ABORT;
3402 goto out;
3403 }
3404
3405 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3406 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3407 file, linenum, args[0], args[1]);
3408 err_code |= ERR_ALERT | ERR_FATAL;
3409 goto out;
3410 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003411 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3412 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3413 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003414 err_code |= ERR_ALERT | ERR_FATAL;
3415 goto out;
3416 }
3417
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003418 err_code |= warnif_cond_conflicts(cond,
3419 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3420 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003421
3422 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3423 rule->cond = cond;
3424 LIST_INIT(&rule->list);
3425 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003426 } else if (!strcmp(args[1], "uri")) {
3427 if (*(args[2]) == 0) {
3428 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003429 err_code |= ERR_ALERT | ERR_FATAL;
3430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3432 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003433 err_code |= ERR_ALERT | ERR_ABORT;
3434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003435 }
3436 } else if (!strcmp(args[1], "realm")) {
3437 if (*(args[2]) == 0) {
3438 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003439 err_code |= ERR_ALERT | ERR_FATAL;
3440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003441 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3442 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003443 err_code |= ERR_ALERT | ERR_ABORT;
3444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003445 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003446 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003447 unsigned interval;
3448
3449 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3450 if (err) {
3451 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3452 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003455 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3456 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003457 err_code |= ERR_ALERT | ERR_ABORT;
3458 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003459 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003460 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003461 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003462
3463 if (curproxy == &defproxy) {
3464 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3465 err_code |= ERR_ALERT | ERR_FATAL;
3466 goto out;
3467 }
3468
3469 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3470 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3471 err_code |= ERR_ALERT | ERR_ABORT;
3472 goto out;
3473 }
3474
Willy Tarreauff011f22011-01-06 17:51:27 +01003475 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3476 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003477 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3478 file, linenum, args[0]);
3479 err_code |= ERR_WARN;
3480 }
3481
Willy Tarreauff011f22011-01-06 17:51:27 +01003482 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003483
Willy Tarreauff011f22011-01-06 17:51:27 +01003484 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003485 err_code |= ERR_ALERT | ERR_ABORT;
3486 goto out;
3487 }
3488
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003489 err_code |= warnif_cond_conflicts(rule->cond,
3490 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3491 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003492 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003493
Willy Tarreaubaaee002006-06-26 02:48:02 +02003494 } else if (!strcmp(args[1], "auth")) {
3495 if (*(args[2]) == 0) {
3496 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003497 err_code |= ERR_ALERT | ERR_FATAL;
3498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003499 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3500 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003501 err_code |= ERR_ALERT | ERR_ABORT;
3502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003503 }
3504 } else if (!strcmp(args[1], "scope")) {
3505 if (*(args[2]) == 0) {
3506 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003507 err_code |= ERR_ALERT | ERR_FATAL;
3508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003509 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3510 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003511 err_code |= ERR_ALERT | ERR_ABORT;
3512 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003513 }
3514 } else if (!strcmp(args[1], "enable")) {
3515 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3516 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003517 err_code |= ERR_ALERT | ERR_ABORT;
3518 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003519 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003520 } else if (!strcmp(args[1], "hide-version")) {
3521 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3522 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003523 err_code |= ERR_ALERT | ERR_ABORT;
3524 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003525 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003526 } else if (!strcmp(args[1], "show-legends")) {
3527 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3528 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3529 err_code |= ERR_ALERT | ERR_ABORT;
3530 goto out;
3531 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003532 } else if (!strcmp(args[1], "show-node")) {
3533
3534 if (*args[2]) {
3535 int i;
3536 char c;
3537
3538 for (i=0; args[2][i]; i++) {
3539 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003540 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3541 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003542 break;
3543 }
3544
3545 if (!i || args[2][i]) {
3546 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3547 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3548 file, linenum, args[0], args[1]);
3549 err_code |= ERR_ALERT | ERR_FATAL;
3550 goto out;
3551 }
3552 }
3553
3554 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3555 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3556 err_code |= ERR_ALERT | ERR_ABORT;
3557 goto out;
3558 }
3559 } else if (!strcmp(args[1], "show-desc")) {
3560 char *desc = NULL;
3561
3562 if (*args[2]) {
3563 int i, len=0;
3564 char *d;
3565
Willy Tarreau348acfe2014-04-14 15:00:39 +02003566 for (i = 2; *args[i]; i++)
3567 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003568
3569 desc = d = (char *)calloc(1, len);
3570
Willy Tarreau348acfe2014-04-14 15:00:39 +02003571 d += snprintf(d, desc + len - d, "%s", args[2]);
3572 for (i = 3; *args[i]; i++)
3573 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003574 }
3575
3576 if (!*args[2] && !global.desc)
3577 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3578 file, linenum, args[1]);
3579 else {
3580 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3581 free(desc);
3582 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3583 err_code |= ERR_ALERT | ERR_ABORT;
3584 goto out;
3585 }
3586 free(desc);
3587 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003588 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003589stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003590 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 +01003591 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003592 err_code |= ERR_ALERT | ERR_FATAL;
3593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003594 }
3595 }
3596 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003597 int optnum;
3598
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003599 if (*(args[1]) == '\0') {
3600 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3601 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003602 err_code |= ERR_ALERT | ERR_FATAL;
3603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003604 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003605
3606 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3607 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003608 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3609 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3610 file, linenum, cfg_opts[optnum].name);
3611 err_code |= ERR_ALERT | ERR_FATAL;
3612 goto out;
3613 }
Willy Tarreau93893792009-07-23 13:19:11 +02003614 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3615 err_code |= ERR_WARN;
3616 goto out;
3617 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003618
Willy Tarreau3842f002009-06-14 11:39:52 +02003619 curproxy->no_options &= ~cfg_opts[optnum].val;
3620 curproxy->options &= ~cfg_opts[optnum].val;
3621
3622 switch (kwm) {
3623 case KWM_STD:
3624 curproxy->options |= cfg_opts[optnum].val;
3625 break;
3626 case KWM_NO:
3627 curproxy->no_options |= cfg_opts[optnum].val;
3628 break;
3629 case KWM_DEF: /* already cleared */
3630 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003631 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003632
Willy Tarreau93893792009-07-23 13:19:11 +02003633 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003634 }
3635 }
3636
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003637 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3638 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003639 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3640 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3641 file, linenum, cfg_opts2[optnum].name);
3642 err_code |= ERR_ALERT | ERR_FATAL;
3643 goto out;
3644 }
Willy Tarreau93893792009-07-23 13:19:11 +02003645 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3646 err_code |= ERR_WARN;
3647 goto out;
3648 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003649
Willy Tarreau3842f002009-06-14 11:39:52 +02003650 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3651 curproxy->options2 &= ~cfg_opts2[optnum].val;
3652
3653 switch (kwm) {
3654 case KWM_STD:
3655 curproxy->options2 |= cfg_opts2[optnum].val;
3656 break;
3657 case KWM_NO:
3658 curproxy->no_options2 |= cfg_opts2[optnum].val;
3659 break;
3660 case KWM_DEF: /* already cleared */
3661 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003662 }
Willy Tarreau93893792009-07-23 13:19:11 +02003663 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003664 }
3665 }
3666
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003667 /* HTTP options override each other. They can be cancelled using
3668 * "no option xxx" which only switches to default mode if the mode
3669 * was this one (useful for cancelling options set in defaults
3670 * sections).
3671 */
3672 if (strcmp(args[1], "httpclose") == 0) {
3673 if (kwm == KWM_STD) {
3674 curproxy->options &= ~PR_O_HTTP_MODE;
3675 curproxy->options |= PR_O_HTTP_PCL;
3676 goto out;
3677 }
3678 else if (kwm == KWM_NO) {
3679 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3680 curproxy->options &= ~PR_O_HTTP_MODE;
3681 goto out;
3682 }
3683 }
3684 else if (strcmp(args[1], "forceclose") == 0) {
3685 if (kwm == KWM_STD) {
3686 curproxy->options &= ~PR_O_HTTP_MODE;
3687 curproxy->options |= PR_O_HTTP_FCL;
3688 goto out;
3689 }
3690 else if (kwm == KWM_NO) {
3691 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3692 curproxy->options &= ~PR_O_HTTP_MODE;
3693 goto out;
3694 }
3695 }
3696 else if (strcmp(args[1], "http-server-close") == 0) {
3697 if (kwm == KWM_STD) {
3698 curproxy->options &= ~PR_O_HTTP_MODE;
3699 curproxy->options |= PR_O_HTTP_SCL;
3700 goto out;
3701 }
3702 else if (kwm == KWM_NO) {
3703 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3704 curproxy->options &= ~PR_O_HTTP_MODE;
3705 goto out;
3706 }
3707 }
3708 else if (strcmp(args[1], "http-keep-alive") == 0) {
3709 if (kwm == KWM_STD) {
3710 curproxy->options &= ~PR_O_HTTP_MODE;
3711 curproxy->options |= PR_O_HTTP_KAL;
3712 goto out;
3713 }
3714 else if (kwm == KWM_NO) {
3715 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3716 curproxy->options &= ~PR_O_HTTP_MODE;
3717 goto out;
3718 }
3719 }
3720 else if (strcmp(args[1], "http-tunnel") == 0) {
3721 if (kwm == KWM_STD) {
3722 curproxy->options &= ~PR_O_HTTP_MODE;
3723 curproxy->options |= PR_O_HTTP_TUN;
3724 goto out;
3725 }
3726 else if (kwm == KWM_NO) {
3727 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3728 curproxy->options &= ~PR_O_HTTP_MODE;
3729 goto out;
3730 }
3731 }
3732
Willy Tarreau3842f002009-06-14 11:39:52 +02003733 if (kwm != KWM_STD) {
3734 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003735 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003738 }
3739
Emeric Brun3a058f32009-06-30 18:26:00 +02003740 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003741 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003742 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003743 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003744 if (*(args[2]) != '\0') {
3745 if (!strcmp(args[2], "clf")) {
3746 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003747 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003748 } else {
3749 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003750 err_code |= ERR_ALERT | ERR_FATAL;
3751 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003752 }
3753 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003754 if (curproxy->conf.logformat_string != default_http_log_format &&
3755 curproxy->conf.logformat_string != default_tcp_log_format &&
3756 curproxy->conf.logformat_string != clf_http_log_format)
3757 free(curproxy->conf.logformat_string);
3758 curproxy->conf.logformat_string = logformat;
3759
3760 free(curproxy->conf.lfs_file);
3761 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3762 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003763 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003764 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003765 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003766 if (curproxy->conf.logformat_string != default_http_log_format &&
3767 curproxy->conf.logformat_string != default_tcp_log_format &&
3768 curproxy->conf.logformat_string != clf_http_log_format)
3769 free(curproxy->conf.logformat_string);
3770 curproxy->conf.logformat_string = default_tcp_log_format;
3771
3772 free(curproxy->conf.lfs_file);
3773 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3774 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003775 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776 else if (!strcmp(args[1], "tcpka")) {
3777 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003778 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003779 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003780
3781 if (curproxy->cap & PR_CAP_FE)
3782 curproxy->options |= PR_O_TCP_CLI_KA;
3783 if (curproxy->cap & PR_CAP_BE)
3784 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003785 }
3786 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003787 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_WARN;
3789
Willy Tarreaubaaee002006-06-26 02:48:02 +02003790 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003791 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003792 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003793 curproxy->options2 &= ~PR_O2_CHK_ANY;
3794 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003795 if (!*args[2]) { /* no argument */
3796 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3797 curproxy->check_len = strlen(DEF_CHECK_REQ);
3798 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003799 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003800 curproxy->check_req = (char *)malloc(reqlen);
3801 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003802 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003803 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003804 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 if (*args[4])
3806 reqlen += strlen(args[4]);
3807 else
3808 reqlen += strlen("HTTP/1.0");
3809
3810 curproxy->check_req = (char *)malloc(reqlen);
3811 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003812 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003814 }
3815 else if (!strcmp(args[1], "ssl-hello-chk")) {
3816 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003817 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003818 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003819
Willy Tarreaua534fea2008-08-03 12:19:50 +02003820 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003821 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003822 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003823 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003824 }
Willy Tarreau23677902007-05-08 23:50:35 +02003825 else if (!strcmp(args[1], "smtpchk")) {
3826 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003827 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003828 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003829 curproxy->options2 &= ~PR_O2_CHK_ANY;
3830 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003831
3832 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3833 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3834 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3835 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3836 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3837 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3838 curproxy->check_req = (char *)malloc(reqlen);
3839 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3840 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3841 } else {
3842 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3843 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3844 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3845 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3846 }
3847 }
3848 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003849 else if (!strcmp(args[1], "pgsql-check")) {
3850 /* use PostgreSQL request to check servers' health */
3851 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3852 err_code |= ERR_WARN;
3853
3854 free(curproxy->check_req);
3855 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003856 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003857 curproxy->options2 |= PR_O2_PGSQL_CHK;
3858
3859 if (*(args[2])) {
3860 int cur_arg = 2;
3861
3862 while (*(args[cur_arg])) {
3863 if (strcmp(args[cur_arg], "user") == 0) {
3864 char * packet;
3865 uint32_t packet_len;
3866 uint32_t pv;
3867
3868 /* suboption header - needs additional argument for it */
3869 if (*(args[cur_arg+1]) == 0) {
3870 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3871 file, linenum, args[0], args[1], args[cur_arg]);
3872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
3874 }
3875
3876 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3877 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3878 pv = htonl(0x30000); /* protocol version 3.0 */
3879
3880 packet = (char*) calloc(1, packet_len);
3881
3882 memcpy(packet + 4, &pv, 4);
3883
3884 /* copy "user" */
3885 memcpy(packet + 8, "user", 4);
3886
3887 /* copy username */
3888 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3889
3890 free(curproxy->check_req);
3891 curproxy->check_req = packet;
3892 curproxy->check_len = packet_len;
3893
3894 packet_len = htonl(packet_len);
3895 memcpy(packet, &packet_len, 4);
3896 cur_arg += 2;
3897 } else {
3898 /* unknown suboption - catchall */
3899 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3900 file, linenum, args[0], args[1]);
3901 err_code |= ERR_ALERT | ERR_FATAL;
3902 goto out;
3903 }
3904 } /* end while loop */
3905 }
3906 }
3907
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003908 else if (!strcmp(args[1], "redis-check")) {
3909 /* use REDIS PING request to check servers' health */
3910 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3911 err_code |= ERR_WARN;
3912
3913 free(curproxy->check_req);
3914 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003915 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003916 curproxy->options2 |= PR_O2_REDIS_CHK;
3917
3918 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3919 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3920 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3921 }
3922
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003923 else if (!strcmp(args[1], "mysql-check")) {
3924 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003925 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3926 err_code |= ERR_WARN;
3927
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003928 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003929 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003930 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003931 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003932
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003933 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003934 * const char mysql40_client_auth_pkt[] = {
3935 * "\x0e\x00\x00" // packet length
3936 * "\x01" // packet number
3937 * "\x00\x00" // client capabilities
3938 * "\x00\x00\x01" // max packet
3939 * "haproxy\x00" // username (null terminated string)
3940 * "\x00" // filler (always 0x00)
3941 * "\x01\x00\x00" // packet length
3942 * "\x00" // packet number
3943 * "\x01" // COM_QUIT command
3944 * };
3945 */
3946
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003947 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
3948 * const char mysql41_client_auth_pkt[] = {
3949 * "\x0e\x00\x00\" // packet length
3950 * "\x01" // packet number
3951 * "\x00\x00\x00\x00" // client capabilities
3952 * "\x00\x00\x00\x01" // max packet
3953 * "\x21" // character set (UTF-8)
3954 * char[23] // All zeroes
3955 * "haproxy\x00" // username (null terminated string)
3956 * "\x00" // filler (always 0x00)
3957 * "\x01\x00\x00" // packet length
3958 * "\x00" // packet number
3959 * "\x01" // COM_QUIT command
3960 * };
3961 */
3962
3963
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003964 if (*(args[2])) {
3965 int cur_arg = 2;
3966
3967 while (*(args[cur_arg])) {
3968 if (strcmp(args[cur_arg], "user") == 0) {
3969 char *mysqluser;
3970 int packetlen, reqlen, userlen;
3971
3972 /* suboption header - needs additional argument for it */
3973 if (*(args[cur_arg+1]) == 0) {
3974 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3975 file, linenum, args[0], args[1], args[cur_arg]);
3976 err_code |= ERR_ALERT | ERR_FATAL;
3977 goto out;
3978 }
3979 mysqluser = args[cur_arg + 1];
3980 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003981
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003982 if (*(args[cur_arg+2])) {
3983 if (!strcmp(args[cur_arg+2], "post-41")) {
3984 packetlen = userlen + 7 + 27;
3985 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003986
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003987 free(curproxy->check_req);
3988 curproxy->check_req = (char *)calloc(1, reqlen);
3989 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003990
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003991 snprintf(curproxy->check_req, 4, "%c%c%c",
3992 ((unsigned char) packetlen & 0xff),
3993 ((unsigned char) (packetlen >> 8) & 0xff),
3994 ((unsigned char) (packetlen >> 16) & 0xff));
3995
3996 curproxy->check_req[3] = 1;
3997 curproxy->check_req[5] = 130;
3998 curproxy->check_req[11] = 1;
3999 curproxy->check_req[12] = 33;
4000 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4001 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4002 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4003 cur_arg += 3;
4004 } else {
4005 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4006 err_code |= ERR_ALERT | ERR_FATAL;
4007 goto out;
4008 }
4009 } else {
4010 packetlen = userlen + 7;
4011 reqlen = packetlen + 9;
4012
4013 free(curproxy->check_req);
4014 curproxy->check_req = (char *)calloc(1, reqlen);
4015 curproxy->check_len = reqlen;
4016
4017 snprintf(curproxy->check_req, 4, "%c%c%c",
4018 ((unsigned char) packetlen & 0xff),
4019 ((unsigned char) (packetlen >> 8) & 0xff),
4020 ((unsigned char) (packetlen >> 16) & 0xff));
4021
4022 curproxy->check_req[3] = 1;
4023 curproxy->check_req[5] = 128;
4024 curproxy->check_req[8] = 1;
4025 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4026 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4027 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4028 cur_arg += 2;
4029 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004030 } else {
4031 /* unknown suboption - catchall */
4032 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4033 file, linenum, args[0], args[1]);
4034 err_code |= ERR_ALERT | ERR_FATAL;
4035 goto out;
4036 }
4037 } /* end while loop */
4038 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004039 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004040 else if (!strcmp(args[1], "ldap-check")) {
4041 /* use LDAP request to check servers' health */
4042 free(curproxy->check_req);
4043 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004044 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004045 curproxy->options2 |= PR_O2_LDAP_CHK;
4046
4047 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4048 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4049 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4050 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004051 else if (!strcmp(args[1], "tcp-check")) {
4052 /* use raw TCPCHK send/expect to check servers' health */
4053 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4054 err_code |= ERR_WARN;
4055
4056 free(curproxy->check_req);
4057 curproxy->check_req = NULL;
4058 curproxy->options2 &= ~PR_O2_CHK_ANY;
4059 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4060 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004061 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004062 int cur_arg;
4063
4064 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4065 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004066 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004067
Willy Tarreau87cf5142011-08-19 22:57:24 +02004068 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004069
4070 free(curproxy->fwdfor_hdr_name);
4071 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4072 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4073
4074 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4075 cur_arg = 2;
4076 while (*(args[cur_arg])) {
4077 if (!strcmp(args[cur_arg], "except")) {
4078 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004079 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004080 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4081 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004084 }
4085 /* flush useless bits */
4086 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004087 cur_arg += 2;
4088 } else if (!strcmp(args[cur_arg], "header")) {
4089 /* suboption header - needs additional argument for it */
4090 if (*(args[cur_arg+1]) == 0) {
4091 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4092 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004095 }
4096 free(curproxy->fwdfor_hdr_name);
4097 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4098 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4099 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004100 } else if (!strcmp(args[cur_arg], "if-none")) {
4101 curproxy->options &= ~PR_O_FF_ALWAYS;
4102 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004103 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004104 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004105 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004106 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004107 err_code |= ERR_ALERT | ERR_FATAL;
4108 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004109 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004110 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004111 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004112 else if (!strcmp(args[1], "originalto")) {
4113 int cur_arg;
4114
4115 /* insert x-original-to field, but not for the IP address listed as an except.
4116 * set default options (ie: bitfield, header name, etc)
4117 */
4118
4119 curproxy->options |= PR_O_ORGTO;
4120
4121 free(curproxy->orgto_hdr_name);
4122 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4123 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4124
Willy Tarreau87cf5142011-08-19 22:57:24 +02004125 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004126 cur_arg = 2;
4127 while (*(args[cur_arg])) {
4128 if (!strcmp(args[cur_arg], "except")) {
4129 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004130 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 +02004131 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4132 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004135 }
4136 /* flush useless bits */
4137 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4138 cur_arg += 2;
4139 } else if (!strcmp(args[cur_arg], "header")) {
4140 /* suboption header - needs additional argument for it */
4141 if (*(args[cur_arg+1]) == 0) {
4142 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4143 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004144 err_code |= ERR_ALERT | ERR_FATAL;
4145 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004146 }
4147 free(curproxy->orgto_hdr_name);
4148 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4149 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4150 cur_arg += 2;
4151 } else {
4152 /* unknown suboption - catchall */
4153 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4154 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004155 err_code |= ERR_ALERT | ERR_FATAL;
4156 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004157 }
4158 } /* end while loop */
4159 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004160 else {
4161 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004162 err_code |= ERR_ALERT | ERR_FATAL;
4163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004164 }
Willy Tarreau93893792009-07-23 13:19:11 +02004165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004166 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004167 else if (!strcmp(args[0], "default_backend")) {
4168 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004169 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004170
4171 if (*(args[1]) == 0) {
4172 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004173 err_code |= ERR_ALERT | ERR_FATAL;
4174 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004175 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004176 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004177 curproxy->defbe.name = strdup(args[1]);
4178 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004179 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004180 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004181 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004182
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004183 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4184 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 +01004185 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004186 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004187 /* enable reconnections to dispatch */
4188 curproxy->options |= PR_O_REDISP;
4189 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004190 else if (!strcmp(args[0], "http-check")) {
4191 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004192 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004193
4194 if (strcmp(args[1], "disable-on-404") == 0) {
4195 /* enable a graceful server shutdown on an HTTP 404 response */
4196 curproxy->options |= PR_O_DISABLE404;
4197 }
Willy Tarreauef781042010-01-27 11:53:01 +01004198 else if (strcmp(args[1], "send-state") == 0) {
4199 /* enable emission of the apparent state of a server in HTTP checks */
4200 curproxy->options2 |= PR_O2_CHK_SNDST;
4201 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004202 else if (strcmp(args[1], "expect") == 0) {
4203 const char *ptr_arg;
4204 int cur_arg;
4205
4206 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4207 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4208 err_code |= ERR_ALERT | ERR_FATAL;
4209 goto out;
4210 }
4211
4212 cur_arg = 2;
4213 /* consider exclamation marks, sole or at the beginning of a word */
4214 while (*(ptr_arg = args[cur_arg])) {
4215 while (*ptr_arg == '!') {
4216 curproxy->options2 ^= PR_O2_EXP_INV;
4217 ptr_arg++;
4218 }
4219 if (*ptr_arg)
4220 break;
4221 cur_arg++;
4222 }
4223 /* now ptr_arg points to the beginning of a word past any possible
4224 * exclamation mark, and cur_arg is the argument which holds this word.
4225 */
4226 if (strcmp(ptr_arg, "status") == 0) {
4227 if (!*(args[cur_arg + 1])) {
4228 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4229 file, linenum, args[0], args[1], ptr_arg);
4230 err_code |= ERR_ALERT | ERR_FATAL;
4231 goto out;
4232 }
4233 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004234 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004235 curproxy->expect_str = strdup(args[cur_arg + 1]);
4236 }
4237 else if (strcmp(ptr_arg, "string") == 0) {
4238 if (!*(args[cur_arg + 1])) {
4239 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4240 file, linenum, args[0], args[1], ptr_arg);
4241 err_code |= ERR_ALERT | ERR_FATAL;
4242 goto out;
4243 }
4244 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004245 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004246 curproxy->expect_str = strdup(args[cur_arg + 1]);
4247 }
4248 else if (strcmp(ptr_arg, "rstatus") == 0) {
4249 if (!*(args[cur_arg + 1])) {
4250 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4251 file, linenum, args[0], args[1], ptr_arg);
4252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
4254 }
4255 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004256 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004257 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004258 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004259 free(curproxy->expect_regex);
4260 curproxy->expect_regex = NULL;
4261 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004262 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004263 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4264 error = NULL;
4265 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4266 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4267 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4268 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004269 err_code |= ERR_ALERT | ERR_FATAL;
4270 goto out;
4271 }
4272 }
4273 else if (strcmp(ptr_arg, "rstring") == 0) {
4274 if (!*(args[cur_arg + 1])) {
4275 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4276 file, linenum, args[0], args[1], ptr_arg);
4277 err_code |= ERR_ALERT | ERR_FATAL;
4278 goto out;
4279 }
4280 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004281 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004282 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004283 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004284 free(curproxy->expect_regex);
4285 curproxy->expect_regex = NULL;
4286 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004287 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004288 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4289 error = NULL;
4290 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4291 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4292 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4293 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004294 err_code |= ERR_ALERT | ERR_FATAL;
4295 goto out;
4296 }
4297 }
4298 else {
4299 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4300 file, linenum, args[0], args[1], ptr_arg);
4301 err_code |= ERR_ALERT | ERR_FATAL;
4302 goto out;
4303 }
4304 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004305 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004306 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 +02004307 err_code |= ERR_ALERT | ERR_FATAL;
4308 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004309 }
4310 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004311 else if (!strcmp(args[0], "tcp-check")) {
4312 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4313 err_code |= ERR_WARN;
4314
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004315 if (strcmp(args[1], "connect") == 0) {
4316 const char *ptr_arg;
4317 int cur_arg;
4318 struct tcpcheck_rule *tcpcheck;
4319 struct list *l;
4320
4321 /* check if first rule is also a 'connect' action */
4322 l = (struct list *)&curproxy->tcpcheck_rules;
4323 if (l->p != l->n) {
4324 tcpcheck = (struct tcpcheck_rule *)l->n;
4325 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4326 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4327 file, linenum);
4328 err_code |= ERR_ALERT | ERR_FATAL;
4329 goto out;
4330 }
4331 }
4332
4333 cur_arg = 2;
4334 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4335 tcpcheck->action = TCPCHK_ACT_CONNECT;
4336
4337 /* parsing each parameters to fill up the rule */
4338 while (*(ptr_arg = args[cur_arg])) {
4339 /* tcp port */
4340 if (strcmp(args[cur_arg], "port") == 0) {
4341 if ( (atol(args[cur_arg + 1]) > 65535) ||
4342 (atol(args[cur_arg + 1]) < 1) ){
4343 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4344 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4345 err_code |= ERR_ALERT | ERR_FATAL;
4346 goto out;
4347 }
4348 tcpcheck->port = atol(args[cur_arg + 1]);
4349 cur_arg += 2;
4350 }
4351 /* send proxy protocol */
4352 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4353 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4354 cur_arg++;
4355 }
4356#ifdef USE_OPENSSL
4357 else if (strcmp(args[cur_arg], "ssl") == 0) {
4358 curproxy->options |= PR_O_TCPCHK_SSL;
4359 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4360 cur_arg++;
4361 }
4362#endif /* USE_OPENSSL */
4363 else {
4364#ifdef USE_OPENSSL
4365 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4366#else /* USE_OPENSSL */
4367 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4368#endif /* USE_OPENSSL */
4369 file, linenum, args[0], args[1], args[cur_arg]);
4370 err_code |= ERR_ALERT | ERR_FATAL;
4371 goto out;
4372 }
4373
4374 }
4375
4376 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4377 }
4378 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004379 if (! *(args[2]) ) {
4380 /* SEND string expected */
4381 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4382 file, linenum, args[0], args[1], args[2]);
4383 err_code |= ERR_ALERT | ERR_FATAL;
4384 goto out;
4385 } else {
4386 struct tcpcheck_rule *tcpcheck;
4387
4388 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4389
4390 tcpcheck->action = TCPCHK_ACT_SEND;
4391 tcpcheck->string_len = strlen(args[2]);
4392 tcpcheck->string = strdup(args[2]);
4393 tcpcheck->expect_regex = NULL;
4394
4395 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4396 }
4397 }
4398 else if (strcmp(args[1], "send-binary") == 0) {
4399 if (! *(args[2]) ) {
4400 /* SEND binary string expected */
4401 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4402 file, linenum, args[0], args[1], args[2]);
4403 err_code |= ERR_ALERT | ERR_FATAL;
4404 goto out;
4405 } else {
4406 struct tcpcheck_rule *tcpcheck;
4407 char *err = NULL;
4408
4409 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4410
4411 tcpcheck->action = TCPCHK_ACT_SEND;
4412 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4413 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4414 file, linenum, args[0], args[1], args[2], err);
4415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
4417 }
4418 tcpcheck->expect_regex = NULL;
4419
4420 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4421 }
4422 }
4423 else if (strcmp(args[1], "expect") == 0) {
4424 const char *ptr_arg;
4425 int cur_arg;
4426 int inverse = 0;
4427
4428 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4429 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4430 err_code |= ERR_ALERT | ERR_FATAL;
4431 goto out;
4432 }
4433
4434 cur_arg = 2;
4435 /* consider exclamation marks, sole or at the beginning of a word */
4436 while (*(ptr_arg = args[cur_arg])) {
4437 while (*ptr_arg == '!') {
4438 inverse = !inverse;
4439 ptr_arg++;
4440 }
4441 if (*ptr_arg)
4442 break;
4443 cur_arg++;
4444 }
4445 /* now ptr_arg points to the beginning of a word past any possible
4446 * exclamation mark, and cur_arg is the argument which holds this word.
4447 */
4448 if (strcmp(ptr_arg, "binary") == 0) {
4449 if (!*(args[cur_arg + 1])) {
4450 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4451 file, linenum, args[0], args[1], ptr_arg);
4452 err_code |= ERR_ALERT | ERR_FATAL;
4453 goto out;
4454 }
4455 struct tcpcheck_rule *tcpcheck;
4456 char *err = NULL;
4457
4458 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4459
4460 tcpcheck->action = TCPCHK_ACT_EXPECT;
4461 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4462 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4463 file, linenum, args[0], args[1], args[2], err);
4464 err_code |= ERR_ALERT | ERR_FATAL;
4465 goto out;
4466 }
4467 tcpcheck->expect_regex = NULL;
4468 tcpcheck->inverse = inverse;
4469
4470 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4471 }
4472 else if (strcmp(ptr_arg, "string") == 0) {
4473 if (!*(args[cur_arg + 1])) {
4474 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4475 file, linenum, args[0], args[1], ptr_arg);
4476 err_code |= ERR_ALERT | ERR_FATAL;
4477 goto out;
4478 }
4479 struct tcpcheck_rule *tcpcheck;
4480
4481 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4482
4483 tcpcheck->action = TCPCHK_ACT_EXPECT;
4484 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4485 tcpcheck->string = strdup(args[cur_arg + 1]);
4486 tcpcheck->expect_regex = NULL;
4487 tcpcheck->inverse = inverse;
4488
4489 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4490 }
4491 else if (strcmp(ptr_arg, "rstring") == 0) {
4492 if (!*(args[cur_arg + 1])) {
4493 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4494 file, linenum, args[0], args[1], ptr_arg);
4495 err_code |= ERR_ALERT | ERR_FATAL;
4496 goto out;
4497 }
4498 struct tcpcheck_rule *tcpcheck;
4499
4500 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4501
4502 tcpcheck->action = TCPCHK_ACT_EXPECT;
4503 tcpcheck->string_len = 0;
4504 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004505 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4506 error = NULL;
4507 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4508 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4509 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4510 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004511 err_code |= ERR_ALERT | ERR_FATAL;
4512 goto out;
4513 }
4514 tcpcheck->inverse = inverse;
4515
4516 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4517 }
4518 else {
4519 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4520 file, linenum, args[0], args[1], ptr_arg);
4521 err_code |= ERR_ALERT | ERR_FATAL;
4522 goto out;
4523 }
4524 }
4525 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004526 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004527 err_code |= ERR_ALERT | ERR_FATAL;
4528 goto out;
4529 }
4530 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004531 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004532 if (curproxy == &defproxy) {
4533 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004534 err_code |= ERR_ALERT | ERR_FATAL;
4535 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004536 }
4537
Willy Tarreaub80c2302007-11-30 20:51:32 +01004538 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004539 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004540
4541 if (strcmp(args[1], "fail") == 0) {
4542 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004543 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004544 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4545 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004546 err_code |= ERR_ALERT | ERR_FATAL;
4547 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004548 }
4549
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004550 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4551 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4552 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004553 err_code |= ERR_ALERT | ERR_FATAL;
4554 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004555 }
4556 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4557 }
4558 else {
4559 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004560 err_code |= ERR_ALERT | ERR_FATAL;
4561 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004562 }
4563 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004564#ifdef TPROXY
4565 else if (!strcmp(args[0], "transparent")) {
4566 /* enable transparent proxy connections */
4567 curproxy->options |= PR_O_TRANSP;
4568 }
4569#endif
4570 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004571 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004572 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004573
Willy Tarreaubaaee002006-06-26 02:48:02 +02004574 if (*(args[1]) == 0) {
4575 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004576 err_code |= ERR_ALERT | ERR_FATAL;
4577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004578 }
4579 curproxy->maxconn = atol(args[1]);
4580 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004581 else if (!strcmp(args[0], "backlog")) { /* backlog */
4582 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004583 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004584
4585 if (*(args[1]) == 0) {
4586 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004587 err_code |= ERR_ALERT | ERR_FATAL;
4588 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004589 }
4590 curproxy->backlog = atol(args[1]);
4591 }
Willy Tarreau86034312006-12-29 00:10:33 +01004592 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004593 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004594 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004595
Willy Tarreau86034312006-12-29 00:10:33 +01004596 if (*(args[1]) == 0) {
4597 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004598 err_code |= ERR_ALERT | ERR_FATAL;
4599 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004600 }
4601 curproxy->fullconn = atol(args[1]);
4602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004603 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4604 if (*(args[1]) == 0) {
4605 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004606 err_code |= ERR_ALERT | ERR_FATAL;
4607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004608 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004609 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4610 if (err) {
4611 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4612 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004613 err_code |= ERR_ALERT | ERR_FATAL;
4614 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004615 }
4616 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004617 }
4618 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004619 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004620 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004621 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004622
Willy Tarreaubaaee002006-06-26 02:48:02 +02004623 if (curproxy == &defproxy) {
4624 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004625 err_code |= ERR_ALERT | ERR_FATAL;
4626 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004627 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004628 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004629 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004630
Willy Tarreau902636f2013-03-10 19:44:48 +01004631 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004632 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004633 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004634 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004635 goto out;
4636 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004637
4638 proto = protocol_by_family(sk->ss_family);
4639 if (!proto || !proto->connect) {
4640 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4641 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004642 err_code |= ERR_ALERT | ERR_FATAL;
4643 goto out;
4644 }
4645
4646 if (port1 != port2) {
4647 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4648 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004649 err_code |= ERR_ALERT | ERR_FATAL;
4650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004651 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004652
4653 if (!port1) {
4654 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4655 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004656 err_code |= ERR_ALERT | ERR_FATAL;
4657 goto out;
4658 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004659
Willy Tarreaud5191e72010-02-09 20:50:45 +01004660 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004661 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004662 }
4663 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004664 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004665 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004666
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004667 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4668 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004669 err_code |= ERR_ALERT | ERR_FATAL;
4670 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004671 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004672 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004673 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004674 /**
4675 * The syntax for hash-type config element is
4676 * hash-type {map-based|consistent} [[<algo>] avalanche]
4677 *
4678 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4679 */
4680 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004681
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004682 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4683 err_code |= ERR_WARN;
4684
4685 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004686 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4687 }
4688 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004689 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4690 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004691 else if (strcmp(args[1], "avalanche") == 0) {
4692 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]);
4693 err_code |= ERR_ALERT | ERR_FATAL;
4694 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004695 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004696 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004697 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004698 err_code |= ERR_ALERT | ERR_FATAL;
4699 goto out;
4700 }
Bhaskar98634f02013-10-29 23:30:51 -04004701
4702 /* set the hash function to use */
4703 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004704 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004705 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004706
4707 /* if consistent with no argument, then avalanche modifier is also applied */
4708 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4709 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004710 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004711 /* set the hash function */
4712 if (!strcmp(args[2], "sdbm")) {
4713 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4714 }
4715 else if (!strcmp(args[2], "djb2")) {
4716 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004717 } else if (!strcmp(args[2], "wt6")) {
4718 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004719 }
4720 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004721 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 -05004722 err_code |= ERR_ALERT | ERR_FATAL;
4723 goto out;
4724 }
4725
4726 /* set the hash modifier */
4727 if (!strcmp(args[3], "avalanche")) {
4728 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4729 }
4730 else if (*args[3]) {
4731 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4732 err_code |= ERR_ALERT | ERR_FATAL;
4733 goto out;
4734 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004735 }
William Lallemanda73203e2012-03-12 12:48:57 +01004736 }
William Lallemanda73203e2012-03-12 12:48:57 +01004737 else if (strcmp(args[0], "unique-id-format") == 0) {
4738 if (!*(args[1])) {
4739 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4740 err_code |= ERR_ALERT | ERR_FATAL;
4741 goto out;
4742 }
William Lallemand3203ff42012-11-11 17:30:56 +01004743 if (*(args[2])) {
4744 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4745 err_code |= ERR_ALERT | ERR_FATAL;
4746 goto out;
4747 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004748 free(curproxy->conf.uniqueid_format_string);
4749 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004750
Willy Tarreau62a61232013-04-12 18:13:46 +02004751 free(curproxy->conf.uif_file);
4752 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4753 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004754 }
William Lallemanda73203e2012-03-12 12:48:57 +01004755
4756 else if (strcmp(args[0], "unique-id-header") == 0) {
4757 if (!*(args[1])) {
4758 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4759 err_code |= ERR_ALERT | ERR_FATAL;
4760 goto out;
4761 }
4762 free(curproxy->header_unique_id);
4763 curproxy->header_unique_id = strdup(args[1]);
4764 }
4765
William Lallemand723b73a2012-02-08 16:37:49 +01004766 else if (strcmp(args[0], "log-format") == 0) {
4767 if (!*(args[1])) {
4768 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4769 err_code |= ERR_ALERT | ERR_FATAL;
4770 goto out;
4771 }
William Lallemand3203ff42012-11-11 17:30:56 +01004772 if (*(args[2])) {
4773 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4774 err_code |= ERR_ALERT | ERR_FATAL;
4775 goto out;
4776 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004777
Willy Tarreau62a61232013-04-12 18:13:46 +02004778 if (curproxy->conf.logformat_string != default_http_log_format &&
4779 curproxy->conf.logformat_string != default_tcp_log_format &&
4780 curproxy->conf.logformat_string != clf_http_log_format)
4781 free(curproxy->conf.logformat_string);
4782 curproxy->conf.logformat_string = strdup(args[1]);
4783
4784 free(curproxy->conf.lfs_file);
4785 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4786 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004787
4788 /* get a chance to improve log-format error reporting by
4789 * reporting the correct line-number when possible.
4790 */
4791 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4792 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4793 file, linenum, curproxy->id);
4794 err_code |= ERR_WARN;
4795 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004796 }
William Lallemand723b73a2012-02-08 16:37:49 +01004797
William Lallemand0f99e342011-10-12 17:50:54 +02004798 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4799 /* delete previous herited or defined syslog servers */
4800 struct logsrv *back;
4801
4802 if (*(args[1]) != 0) {
4803 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4804 err_code |= ERR_ALERT | ERR_FATAL;
4805 goto out;
4806 }
4807
William Lallemand723b73a2012-02-08 16:37:49 +01004808 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4809 LIST_DEL(&tmplogsrv->list);
4810 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004811 }
4812 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004813 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004814 struct logsrv *logsrv;
4815
Willy Tarreaubaaee002006-06-26 02:48:02 +02004816 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004817 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004818 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004819 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004820 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004821 LIST_INIT(&node->list);
4822 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4823 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004824 }
4825 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004826 struct sockaddr_storage *sk;
4827 int port1, port2;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004828 int arg = 0;
4829 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004830
4831 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004832
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004833 /* just after the address, a length may be specified */
4834 if (strcmp(args[arg+2], "len") == 0) {
4835 len = atoi(args[arg+3]);
4836 if (len < 80 || len > 65535) {
4837 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4838 file, linenum, args[arg+3]);
4839 err_code |= ERR_ALERT | ERR_FATAL;
4840 goto out;
4841 }
4842 logsrv->maxlen = len;
4843
4844 /* skip these two args */
4845 arg += 2;
4846 }
4847 else
4848 logsrv->maxlen = MAX_SYSLOG_LEN;
4849
4850 if (logsrv->maxlen > global.max_syslog_len) {
4851 global.max_syslog_len = logsrv->maxlen;
4852 logline = realloc(logline, global.max_syslog_len + 1);
4853 }
4854
4855 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004856 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004857 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004858 err_code |= ERR_ALERT | ERR_FATAL;
4859 goto out;
4860
Willy Tarreaubaaee002006-06-26 02:48:02 +02004861 }
4862
William Lallemand0f99e342011-10-12 17:50:54 +02004863 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004864 if (*(args[arg+3])) {
4865 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004866 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004867 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004868 err_code |= ERR_ALERT | ERR_FATAL;
4869 goto out;
4870
Willy Tarreaubaaee002006-06-26 02:48:02 +02004871 }
4872 }
4873
William Lallemand0f99e342011-10-12 17:50:54 +02004874 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004875 if (*(args[arg+4])) {
4876 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004877 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004878 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004879 err_code |= ERR_ALERT | ERR_FATAL;
4880 goto out;
4881
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004882 }
4883 }
4884
Willy Tarreau902636f2013-03-10 19:44:48 +01004885 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004886 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004887 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004888 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004889 goto out;
4890 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004891
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004892 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004893
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004894 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004895 if (port1 != port2) {
4896 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4897 file, linenum, args[0], args[1]);
4898 err_code |= ERR_ALERT | ERR_FATAL;
4899 goto out;
4900 }
4901
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004902 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004903 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004904 }
William Lallemand0f99e342011-10-12 17:50:54 +02004905
4906 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004907 }
4908 else {
4909 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4910 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004911 err_code |= ERR_ALERT | ERR_FATAL;
4912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004913 }
4914 }
4915 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004916 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004917 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004918 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004919 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004920
Willy Tarreau977b8e42006-12-29 14:19:17 +01004921 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004922 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004923
Willy Tarreaubaaee002006-06-26 02:48:02 +02004924 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004925 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4926 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004927 err_code |= ERR_ALERT | ERR_FATAL;
4928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004929 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004930
4931 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004932 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4933 free(curproxy->conn_src.iface_name);
4934 curproxy->conn_src.iface_name = NULL;
4935 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004936
Willy Tarreau902636f2013-03-10 19:44:48 +01004937 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004938 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004939 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004940 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004941 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004942 goto out;
4943 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004944
4945 proto = protocol_by_family(sk->ss_family);
4946 if (!proto || !proto->connect) {
4947 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004948 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004949 err_code |= ERR_ALERT | ERR_FATAL;
4950 goto out;
4951 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004952
4953 if (port1 != port2) {
4954 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4955 file, linenum, args[0], args[1]);
4956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
4958 }
4959
Willy Tarreauef9a3602012-12-08 22:29:20 +01004960 curproxy->conn_src.source_addr = *sk;
4961 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004962
4963 cur_arg = 2;
4964 while (*(args[cur_arg])) {
4965 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004966#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4967#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02004968 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004969 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4970 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004971 err_code |= ERR_ALERT | ERR_FATAL;
4972 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004973 }
4974#endif
4975 if (!*args[cur_arg + 1]) {
4976 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4977 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004978 err_code |= ERR_ALERT | ERR_FATAL;
4979 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004980 }
4981
4982 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004983 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4984 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004985 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004986 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4987 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004988 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4989 char *name, *end;
4990
4991 name = args[cur_arg+1] + 7;
4992 while (isspace(*name))
4993 name++;
4994
4995 end = name;
4996 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4997 end++;
4998
Willy Tarreauef9a3602012-12-08 22:29:20 +01004999 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5000 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5001 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5002 curproxy->conn_src.bind_hdr_len = end - name;
5003 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5004 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5005 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005006
5007 /* now look for an occurrence number */
5008 while (isspace(*end))
5009 end++;
5010 if (*end == ',') {
5011 end++;
5012 name = end;
5013 if (*end == '-')
5014 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005015 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005016 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005017 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005018 }
5019
Willy Tarreauef9a3602012-12-08 22:29:20 +01005020 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005021 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5022 " occurrences values smaller than %d.\n",
5023 file, linenum, MAX_HDR_HISTORY);
5024 err_code |= ERR_ALERT | ERR_FATAL;
5025 goto out;
5026 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005027 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005028 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005029
Willy Tarreau902636f2013-03-10 19:44:48 +01005030 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005031 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005032 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005033 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005034 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005035 goto out;
5036 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005037
5038 proto = protocol_by_family(sk->ss_family);
5039 if (!proto || !proto->connect) {
5040 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5041 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005042 err_code |= ERR_ALERT | ERR_FATAL;
5043 goto out;
5044 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005045
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005046 if (port1 != port2) {
5047 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5048 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005049 err_code |= ERR_ALERT | ERR_FATAL;
5050 goto out;
5051 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005052 curproxy->conn_src.tproxy_addr = *sk;
5053 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005054 }
5055 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005056#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005057 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005058#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005059#else /* no TPROXY support */
5060 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005061 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005062 err_code |= ERR_ALERT | ERR_FATAL;
5063 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005064#endif
5065 cur_arg += 2;
5066 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005067 }
5068
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005069 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5070#ifdef SO_BINDTODEVICE
5071 if (!*args[cur_arg + 1]) {
5072 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5073 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005074 err_code |= ERR_ALERT | ERR_FATAL;
5075 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005076 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005077 free(curproxy->conn_src.iface_name);
5078 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5079 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005080 global.last_checks |= LSTCHK_NETADM;
5081#else
5082 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5083 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005084 err_code |= ERR_ALERT | ERR_FATAL;
5085 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005086#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005087 cur_arg += 2;
5088 continue;
5089 }
5090 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005091 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005092 err_code |= ERR_ALERT | ERR_FATAL;
5093 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005094 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005095 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005096 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5097 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5098 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005101 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005103 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005104 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5105 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005106 err_code |= ERR_ALERT | ERR_FATAL;
5107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005108 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005109
5110 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005111 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005112 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005113 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005114 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005115 }
5116 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005117 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005118 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005119 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005120 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005122 }
5123 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005124 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005125 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005126 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005127 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005129 }
5130 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005131 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005132 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005133 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005134 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005136 }
5137 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005138 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005139 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005140 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005141 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005143 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005144 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005145 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005146 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005147 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005148 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005149 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005150 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005151 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005152 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005153 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005154 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005155 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005156 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005157
5158 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5159 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 +01005160 }
5161 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005162 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005163 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005164 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005165 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005166 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005167
5168 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5169 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 +01005170 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005171 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005172 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005173 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5174 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005175 err_code |= ERR_ALERT | ERR_FATAL;
5176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005177 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005178
5179 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005180 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005181 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005182 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005184 }
5185 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005186 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005187 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005188 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005189 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005191 }
5192 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005193 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005194 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005195 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005196 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005198 }
5199 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005200 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005201 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005202 args[0], args[1], NULL, (const char **)args+2);
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], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
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_ALLOW, REG_ICASE,
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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005213 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
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_TARPIT, REG_ICASE,
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 Tarreaub8750a82006-09-03 09:56:00 +02005219 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005220 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005221 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005222
Willy Tarreaubaaee002006-06-26 02:48:02 +02005223 if (curproxy == &defproxy) {
5224 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005225 err_code |= ERR_ALERT | ERR_FATAL;
5226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005227 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005228 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005229 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005230
Willy Tarreaubaaee002006-06-26 02:48:02 +02005231 if (*(args[1]) == 0) {
5232 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005233 err_code |= ERR_ALERT | ERR_FATAL;
5234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005235 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005236
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005237 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005238 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5239 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5240 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005241 err_code |= ERR_ALERT | ERR_FATAL;
5242 goto out;
5243 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005244 err_code |= warnif_cond_conflicts(cond,
5245 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5246 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005247 }
5248 else if (*args[2]) {
5249 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5250 file, linenum, args[0], args[2]);
5251 err_code |= ERR_ALERT | ERR_FATAL;
5252 goto out;
5253 }
5254
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005255 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005256 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005257 wl->s = strdup(args[1]);
5258 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005259 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005260 }
5261 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
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 Tarreau977b8e42006-12-29 14:19:17 +01005268
Willy Tarreauade5ec42010-01-28 19:33:49 +01005269 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005270 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +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], "rspdel")) { /* delete response header from a regex */
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_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +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], "rspdeny")) { /* block response header from a regex */
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_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +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], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005290 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5292 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005293 err_code |= ERR_ALERT | ERR_FATAL;
5294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005295 }
5296
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_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005299 args[0], args[1], args[2], (const char **)args+3);
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 }
5303 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a 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_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +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 Tarreaubaaee002006-06-26 02:48:02 +02005309 }
5310 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005311 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005312 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005313 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005314 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005316 }
5317 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005318 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005319
Willy Tarreaubaaee002006-06-26 02:48:02 +02005320 if (curproxy == &defproxy) {
5321 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005322 err_code |= ERR_ALERT | ERR_FATAL;
5323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005324 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005325 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005326 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005327
Willy Tarreaubaaee002006-06-26 02:48:02 +02005328 if (*(args[1]) == 0) {
5329 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005330 err_code |= ERR_ALERT | ERR_FATAL;
5331 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005332 }
5333
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005334 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005335 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5336 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5337 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005338 err_code |= ERR_ALERT | ERR_FATAL;
5339 goto out;
5340 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005341 err_code |= warnif_cond_conflicts(cond,
5342 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5343 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005344 }
5345 else if (*args[2]) {
5346 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5347 file, linenum, args[0], args[2]);
5348 err_code |= ERR_ALERT | ERR_FATAL;
5349 goto out;
5350 }
5351
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005352 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005353 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005354 wl->s = strdup(args[1]);
5355 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005356 }
5357 else if (!strcmp(args[0], "errorloc") ||
5358 !strcmp(args[0], "errorloc302") ||
5359 !strcmp(args[0], "errorloc303")) { /* error location */
5360 int errnum, errlen;
5361 char *err;
5362
Willy Tarreau977b8e42006-12-29 14:19:17 +01005363 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005364 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005365
Willy Tarreaubaaee002006-06-26 02:48:02 +02005366 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005367 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005368 err_code |= ERR_ALERT | ERR_FATAL;
5369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005370 }
5371
5372 errnum = atol(args[1]);
5373 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005374 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5375 err = malloc(errlen);
5376 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005377 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005378 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5379 err = malloc(errlen);
5380 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005381 }
5382
Willy Tarreau0f772532006-12-23 20:51:41 +01005383 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5384 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005385 chunk_destroy(&curproxy->errmsg[rc]);
5386 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005387 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005388 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005389 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005390
5391 if (rc >= HTTP_ERR_SIZE) {
5392 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5393 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005394 free(err);
5395 }
5396 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005397 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5398 int errnum, errlen, fd;
5399 char *err;
5400 struct stat stat;
5401
5402 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005403 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005404
5405 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005406 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005407 err_code |= ERR_ALERT | ERR_FATAL;
5408 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005409 }
5410
5411 fd = open(args[2], O_RDONLY);
5412 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5413 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5414 file, linenum, args[2], args[1]);
5415 if (fd >= 0)
5416 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005417 err_code |= ERR_ALERT | ERR_FATAL;
5418 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005419 }
5420
Willy Tarreau27a674e2009-08-17 07:23:33 +02005421 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005422 errlen = stat.st_size;
5423 } else {
5424 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005425 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005426 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005427 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005428 }
5429
5430 err = malloc(errlen); /* malloc() must succeed during parsing */
5431 errnum = read(fd, err, errlen);
5432 if (errnum != errlen) {
5433 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5434 file, linenum, args[2], args[1]);
5435 close(fd);
5436 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005437 err_code |= ERR_ALERT | ERR_FATAL;
5438 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005439 }
5440 close(fd);
5441
5442 errnum = atol(args[1]);
5443 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5444 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005445 chunk_destroy(&curproxy->errmsg[rc]);
5446 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005447 break;
5448 }
5449 }
5450
5451 if (rc >= HTTP_ERR_SIZE) {
5452 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5453 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005454 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005455 free(err);
5456 }
5457 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005458 else if (!strcmp(args[0], "compression")) {
5459 struct comp *comp;
5460 if (curproxy->comp == NULL) {
5461 comp = calloc(1, sizeof(struct comp));
5462 curproxy->comp = comp;
5463 } else {
5464 comp = curproxy->comp;
5465 }
5466
5467 if (!strcmp(args[1], "algo")) {
5468 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005469 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005470
William Lallemand82fe75c2012-10-23 10:25:10 +02005471 cur_arg = 2;
5472 if (!*args[cur_arg]) {
5473 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5474 file, linenum, args[0]);
5475 err_code |= ERR_ALERT | ERR_FATAL;
5476 goto out;
5477 }
5478 while (*(args[cur_arg])) {
5479 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5480 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5481 file, linenum, args[0], args[cur_arg]);
5482 err_code |= ERR_ALERT | ERR_FATAL;
5483 goto out;
5484 }
William Lallemand552df672012-11-07 13:21:47 +01005485 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5486 curproxy->comp->algos->end(&ctx);
5487 } else {
5488 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5489 file, linenum, args[0], args[cur_arg]);
5490 err_code |= ERR_ALERT | ERR_FATAL;
5491 goto out;
5492 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005493 cur_arg ++;
5494 continue;
5495 }
5496 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005497 else if (!strcmp(args[1], "offload")) {
5498 comp->offload = 1;
5499 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005500 else if (!strcmp(args[1], "type")) {
5501 int cur_arg;
5502 cur_arg = 2;
5503 if (!*args[cur_arg]) {
5504 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5505 file, linenum, args[0]);
5506 err_code |= ERR_ALERT | ERR_FATAL;
5507 goto out;
5508 }
5509 while (*(args[cur_arg])) {
5510 comp_append_type(comp, args[cur_arg]);
5511 cur_arg ++;
5512 continue;
5513 }
5514 }
5515 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005516 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005517 file, linenum, args[0]);
5518 err_code |= ERR_ALERT | ERR_FATAL;
5519 goto out;
5520 }
5521 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005522 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005523 struct cfg_kw_list *kwl;
5524 int index;
5525
5526 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5527 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5528 if (kwl->kw[index].section != CFG_LISTEN)
5529 continue;
5530 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5531 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005532 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005533 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005534 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005535 err_code |= ERR_ALERT | ERR_FATAL;
5536 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005537 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005538 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005539 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005540 err_code |= ERR_WARN;
5541 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005542 }
Willy Tarreau93893792009-07-23 13:19:11 +02005543 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005544 }
5545 }
5546 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005547
Willy Tarreau6daf3432008-01-22 16:44:08 +01005548 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005549 err_code |= ERR_ALERT | ERR_FATAL;
5550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005551 }
Willy Tarreau93893792009-07-23 13:19:11 +02005552 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005553 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005554 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005555}
5556
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005557int
5558cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5559{
5560
5561 int err_code = 0;
5562 const char *err;
5563
5564 if (!strcmp(args[0], "userlist")) { /* new userlist */
5565 struct userlist *newul;
5566
5567 if (!*args[1]) {
5568 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5569 file, linenum, args[0]);
5570 err_code |= ERR_ALERT | ERR_FATAL;
5571 goto out;
5572 }
5573
5574 err = invalid_char(args[1]);
5575 if (err) {
5576 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5577 file, linenum, *err, args[0], args[1]);
5578 err_code |= ERR_ALERT | ERR_FATAL;
5579 goto out;
5580 }
5581
5582 for (newul = userlist; newul; newul = newul->next)
5583 if (!strcmp(newul->name, args[1])) {
5584 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5585 file, linenum, args[1]);
5586 err_code |= ERR_WARN;
5587 goto out;
5588 }
5589
5590 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5591 if (!newul) {
5592 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5593 err_code |= ERR_ALERT | ERR_ABORT;
5594 goto out;
5595 }
5596
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005597 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005598 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005599 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5600 err_code |= ERR_ALERT | ERR_ABORT;
5601 goto out;
5602 }
5603
5604 newul->next = userlist;
5605 userlist = newul;
5606
5607 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005608 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005609 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005610 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005611
5612 if (!*args[1]) {
5613 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5614 file, linenum, args[0]);
5615 err_code |= ERR_ALERT | ERR_FATAL;
5616 goto out;
5617 }
5618
5619 err = invalid_char(args[1]);
5620 if (err) {
5621 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5622 file, linenum, *err, args[0], args[1]);
5623 err_code |= ERR_ALERT | ERR_FATAL;
5624 goto out;
5625 }
5626
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005627 for (ag = userlist->groups; ag; ag = ag->next)
5628 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005629 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5630 file, linenum, args[1], userlist->name);
5631 err_code |= ERR_ALERT;
5632 goto out;
5633 }
5634
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005635 ag = calloc(1, sizeof(*ag));
5636 if (!ag) {
5637 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5638 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005639 goto out;
5640 }
5641
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005642 ag->name = strdup(args[1]);
5643 if (!ag) {
5644 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5645 err_code |= ERR_ALERT | ERR_ABORT;
5646 goto out;
5647 }
5648
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005649 cur_arg = 2;
5650
5651 while (*args[cur_arg]) {
5652 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005653 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005654 cur_arg += 2;
5655 continue;
5656 } else {
5657 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5658 file, linenum, args[0]);
5659 err_code |= ERR_ALERT | ERR_FATAL;
5660 goto out;
5661 }
5662 }
5663
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005664 ag->next = userlist->groups;
5665 userlist->groups = ag;
5666
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005667 } else if (!strcmp(args[0], "user")) { /* new user */
5668 struct auth_users *newuser;
5669 int cur_arg;
5670
5671 if (!*args[1]) {
5672 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5673 file, linenum, args[0]);
5674 err_code |= ERR_ALERT | ERR_FATAL;
5675 goto out;
5676 }
5677
5678 for (newuser = userlist->users; newuser; newuser = newuser->next)
5679 if (!strcmp(newuser->user, args[1])) {
5680 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5681 file, linenum, args[1], userlist->name);
5682 err_code |= ERR_ALERT;
5683 goto out;
5684 }
5685
5686 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5687 if (!newuser) {
5688 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5689 err_code |= ERR_ALERT | ERR_ABORT;
5690 goto out;
5691 }
5692
5693 newuser->user = strdup(args[1]);
5694
5695 newuser->next = userlist->users;
5696 userlist->users = newuser;
5697
5698 cur_arg = 2;
5699
5700 while (*args[cur_arg]) {
5701 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté2c8d7002014-08-29 20:20:02 +02005702#ifdef CONFIG_HAP_CRYPT
5703 if (!crypt("", args[cur_arg + 1])) {
5704 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
5705 file, linenum, newuser->user);
5706 err_code |= ERR_ALERT | ERR_FATAL;
5707 goto out;
5708 }
5709#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005710 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5711 file, linenum);
5712 err_code |= ERR_ALERT;
5713#endif
5714 newuser->pass = strdup(args[cur_arg + 1]);
5715 cur_arg += 2;
5716 continue;
5717 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5718 newuser->pass = strdup(args[cur_arg + 1]);
5719 newuser->flags |= AU_O_INSECURE;
5720 cur_arg += 2;
5721 continue;
5722 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005723 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005724 cur_arg += 2;
5725 continue;
5726 } else {
5727 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5728 file, linenum, args[0]);
5729 err_code |= ERR_ALERT | ERR_FATAL;
5730 goto out;
5731 }
5732 }
5733 } else {
5734 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5735 err_code |= ERR_ALERT | ERR_FATAL;
5736 }
5737
5738out:
5739 return err_code;
5740}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005741
5742/*
5743 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005744 * Returns the error code, 0 if OK, or any combination of :
5745 * - ERR_ABORT: must abort ASAP
5746 * - ERR_FATAL: we can continue parsing but not start the service
5747 * - ERR_WARN: a warning has been emitted
5748 * - ERR_ALERT: an alert has been emitted
5749 * Only the two first ones can stop processing, the two others are just
5750 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005751 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005752int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005753{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005754 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755 FILE *f;
5756 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005757 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005758 struct cfg_section *cs = NULL;
5759 struct cfg_section *ics;
5760
5761 /* Register internal sections */
5762 if (!cfg_register_section("listen", cfg_parse_listen) ||
5763 !cfg_register_section("frontend", cfg_parse_listen) ||
5764 !cfg_register_section("backend", cfg_parse_listen) ||
5765 !cfg_register_section("ruleset", cfg_parse_listen) ||
5766 !cfg_register_section("defaults", cfg_parse_listen) ||
5767 !cfg_register_section("global", cfg_parse_global) ||
5768 !cfg_register_section("userlist", cfg_parse_users) ||
5769 !cfg_register_section("peers", cfg_parse_peers))
5770 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771
Willy Tarreaubaaee002006-06-26 02:48:02 +02005772 if ((f=fopen(file,"r")) == NULL)
5773 return -1;
5774
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005775 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005776 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005777 char *end;
5778 char *args[MAX_LINE_ARGS + 1];
5779 char *line = thisline;
5780
Willy Tarreaubaaee002006-06-26 02:48:02 +02005781 linenum++;
5782
5783 end = line + strlen(line);
5784
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005785 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5786 /* Check if we reached the limit and the last char is not \n.
5787 * Watch out for the last line without the terminating '\n'!
5788 */
5789 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005790 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005791 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005792 }
5793
Willy Tarreaubaaee002006-06-26 02:48:02 +02005794 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005795 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005796 line++;
5797
5798 arg = 0;
5799 args[arg] = line;
5800
5801 while (*line && arg < MAX_LINE_ARGS) {
5802 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5803 * C equivalent value. Other combinations left unchanged (eg: \1).
5804 */
5805 if (*line == '\\') {
5806 int skip = 0;
5807 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5808 *line = line[1];
5809 skip = 1;
5810 }
5811 else if (line[1] == 'r') {
5812 *line = '\r';
5813 skip = 1;
5814 }
5815 else if (line[1] == 'n') {
5816 *line = '\n';
5817 skip = 1;
5818 }
5819 else if (line[1] == 't') {
5820 *line = '\t';
5821 skip = 1;
5822 }
5823 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005824 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005825 unsigned char hex1, hex2;
5826 hex1 = toupper(line[2]) - '0';
5827 hex2 = toupper(line[3]) - '0';
5828 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5829 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5830 *line = (hex1<<4) + hex2;
5831 skip = 3;
5832 }
5833 else {
5834 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005835 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005836 }
5837 }
5838 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005839 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005840 end -= skip;
5841 }
5842 line++;
5843 }
5844 else if (*line == '#' || *line == '\n' || *line == '\r') {
5845 /* end of string, end of loop */
5846 *line = 0;
5847 break;
5848 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005849 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005850 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005851 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005852 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005853 line++;
5854 args[++arg] = line;
5855 }
5856 else {
5857 line++;
5858 }
5859 }
5860
5861 /* empty line */
5862 if (!**args)
5863 continue;
5864
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005865 if (*line) {
5866 /* we had to stop due to too many args.
5867 * Let's terminate the string, print the offending part then cut the
5868 * last arg.
5869 */
5870 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5871 line++;
5872 *line = '\0';
5873
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005874 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005875 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005876 err_code |= ERR_ALERT | ERR_FATAL;
5877 args[arg] = line;
5878 }
5879
Willy Tarreau540abe42007-05-02 20:50:16 +02005880 /* zero out remaining args and ensure that at least one entry
5881 * is zeroed out.
5882 */
5883 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005884 args[arg] = line;
5885 }
5886
Willy Tarreau3842f002009-06-14 11:39:52 +02005887 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005888 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005889 char *tmp;
5890
Willy Tarreau3842f002009-06-14 11:39:52 +02005891 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005892 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005893 for (arg=0; *args[arg+1]; arg++)
5894 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005895 *tmp = '\0'; // fix the next arg to \0
5896 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005897 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005898 else if (!strcmp(args[0], "default")) {
5899 kwm = KWM_DEF;
5900 for (arg=0; *args[arg+1]; arg++)
5901 args[arg] = args[arg+1]; // shift args after inversion
5902 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005903
William Lallemand0f99e342011-10-12 17:50:54 +02005904 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5905 strcmp(args[0], "log") != 0) {
5906 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005907 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005908 }
5909
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005910 /* detect section start */
5911 list_for_each_entry(ics, &sections, list) {
5912 if (strcmp(args[0], ics->section_name) == 0) {
5913 cursection = ics->section_name;
5914 cs = ics;
5915 break;
5916 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005917 }
5918
Willy Tarreaubaaee002006-06-26 02:48:02 +02005919 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005920 if (cs)
5921 err_code |= cs->section_parser(file, linenum, args, kwm);
5922 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005923 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005924 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005925 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005926
5927 if (err_code & ERR_ABORT)
5928 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005929 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005930 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005931 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005932 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005933}
5934
Willy Tarreau5436afc2014-09-16 12:17:36 +02005935/* This function propagates processes from frontend <from> to backend <to> so
5936 * that it is always guaranteed that a backend pointed to by a frontend is
5937 * bound to all of its processes. After that, if the target is a "listen"
5938 * instance, the function recursively descends the target's own targets along
5939 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
5940 * checked first to ensure that <to> is already bound to all processes of
5941 * <from>, there is no risk of looping and we ensure to follow the shortest
5942 * path to the destination.
5943 *
5944 * It is possible to set <to> to NULL for the first call so that the function
5945 * takes care of visiting the initial frontend in <from>.
5946 *
5947 * It is important to note that the function relies on the fact that all names
5948 * have already been resolved.
5949 */
5950void propagate_processes(struct proxy *from, struct proxy *to)
5951{
5952 struct switching_rule *rule;
5953 struct hdr_exp *exp;
5954
5955 if (to) {
5956 /* check whether we need to go down */
5957 if (from->bind_proc &&
5958 (from->bind_proc & to->bind_proc) == from->bind_proc)
5959 return;
5960
5961 if (!from->bind_proc && !to->bind_proc)
5962 return;
5963
5964 to->bind_proc = from->bind_proc ?
5965 (to->bind_proc | from->bind_proc) : 0;
5966
5967 /* now propagate down */
5968 from = to;
5969 }
5970
5971 if (!from->cap & PR_CAP_FE)
5972 return;
5973
5974 /* default_backend */
5975 if (from->defbe.be)
5976 propagate_processes(from, from->defbe.be);
5977
5978 /* use_backend */
5979 list_for_each_entry(rule, &from->switching_rules, list) {
5980 to = rule->be.backend;
5981 propagate_processes(from, to);
5982 }
5983
5984 /* reqsetbe */
5985 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
5986 if (exp->action != ACT_SETBE)
5987 continue;
5988 to = (struct proxy *)exp->replace;
5989 propagate_processes(from, to);
5990 }
5991}
5992
Willy Tarreaubb925012009-07-23 13:36:36 +02005993/*
5994 * Returns the error code, 0 if OK, or any combination of :
5995 * - ERR_ABORT: must abort ASAP
5996 * - ERR_FATAL: we can continue parsing but not start the service
5997 * - ERR_WARN: a warning has been emitted
5998 * - ERR_ALERT: an alert has been emitted
5999 * Only the two first ones can stop processing, the two others are just
6000 * indicators.
6001 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006002int check_config_validity()
6003{
6004 int cfgerr = 0;
6005 struct proxy *curproxy = NULL;
6006 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006007 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006008 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006009 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006010
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006011 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006012 /*
6013 * Now, check for the integrity of all that we have collected.
6014 */
6015
6016 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006017 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006018
Willy Tarreau193b8c62012-11-22 00:17:38 +01006019 if (!global.tune.max_http_hdr)
6020 global.tune.max_http_hdr = MAX_HTTP_HDR;
6021
6022 if (!global.tune.cookie_len)
6023 global.tune.cookie_len = CAPTURE_LEN;
6024
6025 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6026
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006027 /* Post initialisation of the users and groups lists. */
6028 err_code = userlist_postinit();
6029 if (err_code != ERR_NONE)
6030 goto out;
6031
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006032 /* first, we will invert the proxy list order */
6033 curproxy = NULL;
6034 while (proxy) {
6035 struct proxy *next;
6036
6037 next = proxy->next;
6038 proxy->next = curproxy;
6039 curproxy = proxy;
6040 if (!next)
6041 break;
6042 proxy = next;
6043 }
6044
Willy Tarreaubaaee002006-06-26 02:48:02 +02006045 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006046 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006047 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006048 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006049 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006050 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006051 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006052 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006053
Willy Tarreau050536d2012-10-04 08:47:34 +02006054 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006055 /* proxy ID not set, use automatic numbering with first
6056 * spare entry starting with next_pxid.
6057 */
6058 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6059 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6060 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006061 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006062 next_pxid++;
6063
Willy Tarreau55ea7572007-06-17 19:56:27 +02006064
Willy Tarreaubaaee002006-06-26 02:48:02 +02006065 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006066 /* ensure we don't keep listeners uselessly bound */
6067 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006068 curproxy = curproxy->next;
6069 continue;
6070 }
6071
Willy Tarreau102df612014-05-07 23:56:38 +02006072 /* Check multi-process mode compatibility for the current proxy */
6073
6074 if (curproxy->bind_proc) {
6075 /* an explicit bind-process was specified, let's check how many
6076 * processes remain.
6077 */
6078 nbproc = popcount(curproxy->bind_proc);
6079
6080 curproxy->bind_proc &= nbits(global.nbproc);
6081 if (!curproxy->bind_proc && nbproc == 1) {
6082 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);
6083 curproxy->bind_proc = 1;
6084 }
6085 else if (!curproxy->bind_proc && nbproc > 1) {
6086 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);
6087 curproxy->bind_proc = 0;
6088 }
6089 }
6090
Willy Tarreau3d209582014-05-09 17:06:11 +02006091 /* check and reduce the bind-proc of each listener */
6092 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6093 unsigned long mask;
6094
6095 if (!bind_conf->bind_proc)
6096 continue;
6097
6098 mask = nbits(global.nbproc);
6099 if (curproxy->bind_proc)
6100 mask &= curproxy->bind_proc;
6101 /* mask cannot be null here thanks to the previous checks */
6102
6103 nbproc = popcount(bind_conf->bind_proc);
6104 bind_conf->bind_proc &= mask;
6105
6106 if (!bind_conf->bind_proc && nbproc == 1) {
6107 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",
6108 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6109 bind_conf->bind_proc = mask & ~(mask - 1);
6110 }
6111 else if (!bind_conf->bind_proc && nbproc > 1) {
6112 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",
6113 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6114 bind_conf->bind_proc = 0;
6115 }
6116 }
6117
Willy Tarreau102df612014-05-07 23:56:38 +02006118 /* here, if bind_proc is null, it means no limit, otherwise it's explicit.
6119 * We now check how many processes the proxy will effectively run on.
6120 */
6121
6122 nbproc = global.nbproc;
6123 if (curproxy->bind_proc)
6124 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
6125
6126 if (global.nbproc > 1 && curproxy->table.peers.name) {
6127 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6128 curproxy->id);
6129 cfgerr++;
6130 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006131
Willy Tarreauff01a212009-03-15 13:46:16 +01006132 switch (curproxy->mode) {
6133 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006134 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006135 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006136 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6137 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006138 cfgerr++;
6139 }
6140
6141 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006142 Warning("config : servers will be ignored for %s '%s'.\n",
6143 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006144 break;
6145
6146 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006147 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006148 break;
6149
6150 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006151 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006152 break;
6153 }
6154
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006155 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006156 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006157 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006158 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6159 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006160 cfgerr++;
6161 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006162#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006163 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006164 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6165 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006166 cfgerr++;
6167 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006168#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006169 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006170 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6171 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006172 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006173 }
6174 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006175 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006176 /* If no LB algo is set in a backend, and we're not in
6177 * transparent mode, dispatch mode nor proxy mode, we
6178 * want to use balance roundrobin by default.
6179 */
6180 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6181 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006182 }
6183 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006184
Willy Tarreau1620ec32011-08-06 17:05:02 +02006185 if (curproxy->options & PR_O_DISPATCH)
6186 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6187 else if (curproxy->options & PR_O_HTTP_PROXY)
6188 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6189 else if (curproxy->options & PR_O_TRANSP)
6190 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006191
Willy Tarreau1620ec32011-08-06 17:05:02 +02006192 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6193 if (curproxy->options & PR_O_DISABLE404) {
6194 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6195 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6196 err_code |= ERR_WARN;
6197 curproxy->options &= ~PR_O_DISABLE404;
6198 }
6199 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6200 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6201 "send-state", proxy_type_str(curproxy), curproxy->id);
6202 err_code |= ERR_WARN;
6203 curproxy->options &= ~PR_O2_CHK_SNDST;
6204 }
Willy Tarreauef781042010-01-27 11:53:01 +01006205 }
6206
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006207 /* if a default backend was specified, let's find it */
6208 if (curproxy->defbe.name) {
6209 struct proxy *target;
6210
Alex Williams96532db2009-11-01 21:27:13 -05006211 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006212 if (!target) {
6213 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6214 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006215 cfgerr++;
6216 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006217 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6218 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006219 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006220 } else {
6221 free(curproxy->defbe.name);
6222 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006223
6224 /* Emit a warning if this proxy also has some servers */
6225 if (curproxy->srv) {
6226 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6227 curproxy->id);
6228 err_code |= ERR_WARN;
6229 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006230 }
6231 }
6232
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006233 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006234 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6235 /* map jump target for ACT_SETBE in req_rep chain */
6236 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006237 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006238 struct proxy *target;
6239
Willy Tarreaua496b602006-12-17 23:15:24 +01006240 if (exp->action != ACT_SETBE)
6241 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006242
Alex Williams96532db2009-11-01 21:27:13 -05006243 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006244 if (!target) {
6245 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6246 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006247 cfgerr++;
6248 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006249 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6250 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006251 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006252 } else {
6253 free((void *)exp->replace);
6254 exp->replace = (const char *)target;
6255 }
6256 }
6257 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006258
6259 /* find the target proxy for 'use_backend' rules */
6260 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006261 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006262 struct logformat_node *node;
6263 char *pxname;
6264
6265 /* Try to parse the string as a log format expression. If the result
6266 * of the parsing is only one entry containing a simple string, then
6267 * it's a standard string corresponding to a static rule, thus the
6268 * parsing is cancelled and be.name is restored to be resolved.
6269 */
6270 pxname = rule->be.name;
6271 LIST_INIT(&rule->be.expr);
6272 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6273 curproxy->conf.args.file, curproxy->conf.args.line);
6274 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6275
6276 if (!LIST_ISEMPTY(&rule->be.expr)) {
6277 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6278 rule->dynamic = 1;
6279 free(pxname);
6280 continue;
6281 }
6282 /* simple string: free the expression and fall back to static rule */
6283 free(node->arg);
6284 free(node);
6285 }
6286
6287 rule->dynamic = 0;
6288 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006289
Alex Williams96532db2009-11-01 21:27:13 -05006290 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006291
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006292 if (!target) {
6293 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6294 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006295 cfgerr++;
6296 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006297 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6298 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006299 cfgerr++;
6300 } else {
6301 free((void *)rule->be.name);
6302 rule->be.backend = target;
6303 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006304 }
6305
Willy Tarreau5436afc2014-09-16 12:17:36 +02006306 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006307 list_for_each_entry(srule, &curproxy->server_rules, list) {
6308 struct server *target = findserver(curproxy, srule->srv.name);
6309
6310 if (!target) {
6311 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6312 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6313 cfgerr++;
6314 continue;
6315 }
6316 free((void *)srule->srv.name);
6317 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006318 }
6319
Emeric Brunb982a3d2010-01-04 15:45:53 +01006320 /* find the target table for 'stick' rules */
6321 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6322 struct proxy *target;
6323
Emeric Brun1d33b292010-01-04 15:47:17 +01006324 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6325 if (mrule->flags & STK_IS_STORE)
6326 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6327
Emeric Brunb982a3d2010-01-04 15:45:53 +01006328 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006329 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006330 else
6331 target = curproxy;
6332
6333 if (!target) {
6334 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6335 curproxy->id, mrule->table.name);
6336 cfgerr++;
6337 }
6338 else if (target->table.size == 0) {
6339 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6340 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6341 cfgerr++;
6342 }
Willy Tarreau12785782012-04-27 21:37:17 +02006343 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6344 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006345 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6346 cfgerr++;
6347 }
6348 else {
6349 free((void *)mrule->table.name);
6350 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006351 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006352 }
6353 }
6354
6355 /* find the target table for 'store response' rules */
6356 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6357 struct proxy *target;
6358
Emeric Brun1d33b292010-01-04 15:47:17 +01006359 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6360
Emeric Brunb982a3d2010-01-04 15:45:53 +01006361 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006362 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006363 else
6364 target = curproxy;
6365
6366 if (!target) {
6367 Alert("Proxy '%s': unable to find store table '%s'.\n",
6368 curproxy->id, mrule->table.name);
6369 cfgerr++;
6370 }
6371 else if (target->table.size == 0) {
6372 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6373 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6374 cfgerr++;
6375 }
Willy Tarreau12785782012-04-27 21:37:17 +02006376 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6377 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006378 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6379 cfgerr++;
6380 }
6381 else {
6382 free((void *)mrule->table.name);
6383 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006384 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006385 }
6386 }
6387
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006388 /* find the target table for 'tcp-request' layer 4 rules */
6389 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6390 struct proxy *target;
6391
Willy Tarreaub4c84932013-07-23 19:15:30 +02006392 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006393 continue;
6394
6395 if (trule->act_prm.trk_ctr.table.n)
6396 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6397 else
6398 target = curproxy;
6399
6400 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006401 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6402 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006403 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006404 cfgerr++;
6405 }
6406 else if (target->table.size == 0) {
6407 Alert("Proxy '%s': table '%s' used but not configured.\n",
6408 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6409 cfgerr++;
6410 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006411 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6412 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6413 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 +01006414 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006415 cfgerr++;
6416 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006417 else {
6418 free(trule->act_prm.trk_ctr.table.n);
6419 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006420 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006421 * to pass a list of counters to track and allocate them right here using
6422 * stktable_alloc_data_type().
6423 */
6424 }
6425 }
6426
Willy Tarreaud1f96522010-08-03 19:34:32 +02006427 /* find the target table for 'tcp-request' layer 6 rules */
6428 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6429 struct proxy *target;
6430
Willy Tarreaub4c84932013-07-23 19:15:30 +02006431 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006432 continue;
6433
6434 if (trule->act_prm.trk_ctr.table.n)
6435 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6436 else
6437 target = curproxy;
6438
6439 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006440 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6441 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006442 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006443 cfgerr++;
6444 }
6445 else if (target->table.size == 0) {
6446 Alert("Proxy '%s': table '%s' used but not configured.\n",
6447 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6448 cfgerr++;
6449 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006450 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6451 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6452 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 +01006453 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006454 cfgerr++;
6455 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006456 else {
6457 free(trule->act_prm.trk_ctr.table.n);
6458 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006459 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006460 * to pass a list of counters to track and allocate them right here using
6461 * stktable_alloc_data_type().
6462 */
6463 }
6464 }
6465
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006466 /* move any "block" rules at the beginning of the http-request rules */
6467 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6468 /* insert block_rules into http_req_rules at the beginning */
6469 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6470 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6471 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6472 curproxy->http_req_rules.n = curproxy->block_rules.n;
6473 LIST_INIT(&curproxy->block_rules);
6474 }
6475
Emeric Brun32da3c42010-09-23 18:39:19 +02006476 if (curproxy->table.peers.name) {
6477 struct peers *curpeers = peers;
6478
6479 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6480 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6481 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006482 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006483 break;
6484 }
6485 }
6486
6487 if (!curpeers) {
6488 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6489 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006490 free((void *)curproxy->table.peers.name);
6491 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006492 cfgerr++;
6493 }
6494 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006495 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6496 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006497 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006498 cfgerr++;
6499 }
6500 }
6501
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006502 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006503 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006504 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6505 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6506 "proxy", curproxy->id);
6507 cfgerr++;
6508 goto out_uri_auth_compat;
6509 }
6510
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006511 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006512 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006513 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006514 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006515
Willy Tarreau95fa4692010-02-01 13:05:50 +01006516 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6517 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006518
6519 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006520 uri_auth_compat_req[i++] = "realm";
6521 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6522 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006523
Willy Tarreau95fa4692010-02-01 13:05:50 +01006524 uri_auth_compat_req[i++] = "unless";
6525 uri_auth_compat_req[i++] = "{";
6526 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6527 uri_auth_compat_req[i++] = "}";
6528 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006529
Willy Tarreauff011f22011-01-06 17:51:27 +01006530 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6531 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006532 cfgerr++;
6533 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006534 }
6535
Willy Tarreauff011f22011-01-06 17:51:27 +01006536 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006537
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006538 if (curproxy->uri_auth->auth_realm) {
6539 free(curproxy->uri_auth->auth_realm);
6540 curproxy->uri_auth->auth_realm = NULL;
6541 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006542
6543 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006544 }
6545out_uri_auth_compat:
6546
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006547 /* compile the log format */
6548 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006549 if (curproxy->conf.logformat_string != default_http_log_format &&
6550 curproxy->conf.logformat_string != default_tcp_log_format &&
6551 curproxy->conf.logformat_string != clf_http_log_format)
6552 free(curproxy->conf.logformat_string);
6553 curproxy->conf.logformat_string = NULL;
6554 free(curproxy->conf.lfs_file);
6555 curproxy->conf.lfs_file = NULL;
6556 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006557 }
6558
Willy Tarreau62a61232013-04-12 18:13:46 +02006559 if (curproxy->conf.logformat_string) {
6560 curproxy->conf.args.ctx = ARGC_LOG;
6561 curproxy->conf.args.file = curproxy->conf.lfs_file;
6562 curproxy->conf.args.line = curproxy->conf.lfs_line;
6563 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006564 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006565 curproxy->conf.args.file = NULL;
6566 curproxy->conf.args.line = 0;
6567 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006568
Willy Tarreau62a61232013-04-12 18:13:46 +02006569 if (curproxy->conf.uniqueid_format_string) {
6570 curproxy->conf.args.ctx = ARGC_UIF;
6571 curproxy->conf.args.file = curproxy->conf.uif_file;
6572 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006573 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006574 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6575 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006576 curproxy->conf.args.file = NULL;
6577 curproxy->conf.args.line = 0;
6578 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006579
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006580 /* only now we can check if some args remain unresolved.
6581 * This must be done after the users and groups resolution.
6582 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006583 cfgerr += smp_resolve_args(curproxy);
6584 if (!cfgerr)
6585 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006586
Willy Tarreau2738a142006-07-08 17:28:09 +02006587 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006588 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006589 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006590 (!curproxy->timeout.connect ||
6591 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006592 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006593 " | While not properly invalid, you will certainly encounter various problems\n"
6594 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006595 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006596 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006597 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006598 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006599
Willy Tarreau1fa31262007-12-03 00:36:16 +01006600 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6601 * We must still support older configurations, so let's find out whether those
6602 * parameters have been set or must be copied from contimeouts.
6603 */
6604 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006605 if (!curproxy->timeout.tarpit ||
6606 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006607 /* tarpit timeout not set. We search in the following order:
6608 * default.tarpit, curr.connect, default.connect.
6609 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006610 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006611 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006612 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006613 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006614 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006615 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006616 }
6617 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006618 (!curproxy->timeout.queue ||
6619 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006620 /* queue timeout not set. We search in the following order:
6621 * default.queue, curr.connect, default.connect.
6622 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006623 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006624 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006625 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006626 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006627 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006628 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006629 }
6630 }
6631
Willy Tarreau1620ec32011-08-06 17:05:02 +02006632 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006633 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6634 curproxy->check_req = (char *)malloc(curproxy->check_len);
6635 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006636 }
6637
Willy Tarreau215663d2014-06-13 18:30:23 +02006638 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6639 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6640 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6641 proxy_type_str(curproxy), curproxy->id);
6642 err_code |= ERR_WARN;
6643 }
6644
Willy Tarreau193b8c62012-11-22 00:17:38 +01006645 /* ensure that cookie capture length is not too large */
6646 if (curproxy->capture_len >= global.tune.cookie_len) {
6647 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6648 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6649 err_code |= ERR_WARN;
6650 curproxy->capture_len = global.tune.cookie_len - 1;
6651 }
6652
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006653 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006654 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006655 curproxy->req_cap_pool = create_pool("ptrcap",
6656 curproxy->nb_req_cap * sizeof(char *),
6657 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006658 }
6659
6660 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006661 curproxy->rsp_cap_pool = create_pool("ptrcap",
6662 curproxy->nb_rsp_cap * sizeof(char *),
6663 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006664 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006665
Willy Tarreaubaaee002006-06-26 02:48:02 +02006666 /* first, we will invert the servers list order */
6667 newsrv = NULL;
6668 while (curproxy->srv) {
6669 struct server *next;
6670
6671 next = curproxy->srv->next;
6672 curproxy->srv->next = newsrv;
6673 newsrv = curproxy->srv;
6674 if (!next)
6675 break;
6676 curproxy->srv = next;
6677 }
6678
Willy Tarreau17edc812014-01-03 12:14:34 +01006679 /* Check that no server name conflicts. This causes trouble in the stats.
6680 * We only emit a warning for the first conflict affecting each server,
6681 * in order to avoid combinatory explosion if all servers have the same
6682 * name. We do that only for servers which do not have an explicit ID,
6683 * because these IDs were made also for distinguishing them and we don't
6684 * want to annoy people who correctly manage them.
6685 */
6686 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6687 struct server *other_srv;
6688
6689 if (newsrv->puid)
6690 continue;
6691
6692 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6693 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6694 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6695 newsrv->conf.file, newsrv->conf.line,
6696 proxy_type_str(curproxy), curproxy->id,
6697 newsrv->id, other_srv->conf.line);
6698 break;
6699 }
6700 }
6701 }
6702
Willy Tarreaudd701652010-05-25 23:03:02 +02006703 /* assign automatic UIDs to servers which don't have one yet */
6704 next_id = 1;
6705 newsrv = curproxy->srv;
6706 while (newsrv != NULL) {
6707 if (!newsrv->puid) {
6708 /* server ID not set, use automatic numbering with first
6709 * spare entry starting with next_svid.
6710 */
6711 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6712 newsrv->conf.id.key = newsrv->puid = next_id;
6713 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6714 }
6715 next_id++;
6716 newsrv = newsrv->next;
6717 }
6718
Willy Tarreau20697042007-11-15 23:26:18 +01006719 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006720 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006721
Willy Tarreau62c3be22012-01-20 13:12:32 +01006722 /*
6723 * If this server supports a maxconn parameter, it needs a dedicated
6724 * tasks to fill the emptied slots when a connection leaves.
6725 * Also, resolve deferred tracking dependency if needed.
6726 */
6727 newsrv = curproxy->srv;
6728 while (newsrv != NULL) {
6729 if (newsrv->minconn > newsrv->maxconn) {
6730 /* Only 'minconn' was specified, or it was higher than or equal
6731 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6732 * this will avoid further useless expensive computations.
6733 */
6734 newsrv->maxconn = newsrv->minconn;
6735 } else if (newsrv->maxconn && !newsrv->minconn) {
6736 /* minconn was not specified, so we set it to maxconn */
6737 newsrv->minconn = newsrv->maxconn;
6738 }
6739
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006740#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006741 if (newsrv->use_ssl || newsrv->check.use_ssl)
6742 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006743#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006744
Willy Tarreau2f075e92013-12-03 11:11:34 +01006745 /* set the check type on the server */
6746 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6747
Willy Tarreau62c3be22012-01-20 13:12:32 +01006748 if (newsrv->trackit) {
6749 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006750 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006751 char *pname, *sname;
6752
6753 pname = newsrv->trackit;
6754 sname = strrchr(pname, '/');
6755
6756 if (sname)
6757 *sname++ = '\0';
6758 else {
6759 sname = pname;
6760 pname = NULL;
6761 }
6762
6763 if (pname) {
6764 px = findproxy(pname, PR_CAP_BE);
6765 if (!px) {
6766 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6767 proxy_type_str(curproxy), curproxy->id,
6768 newsrv->id, pname);
6769 cfgerr++;
6770 goto next_srv;
6771 }
6772 } else
6773 px = curproxy;
6774
6775 srv = findserver(px, sname);
6776 if (!srv) {
6777 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6778 proxy_type_str(curproxy), curproxy->id,
6779 newsrv->id, sname);
6780 cfgerr++;
6781 goto next_srv;
6782 }
6783
Willy Tarreau32091232014-05-16 13:52:00 +02006784 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6785 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6786 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006787 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006788 "tracking as it does not have any check nor agent enabled.\n",
6789 proxy_type_str(curproxy), curproxy->id,
6790 newsrv->id, px->id, srv->id);
6791 cfgerr++;
6792 goto next_srv;
6793 }
6794
6795 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6796
6797 if (loop) {
6798 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6799 "belongs to a tracking chain looping back to %s/%s.\n",
6800 proxy_type_str(curproxy), curproxy->id,
6801 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006802 cfgerr++;
6803 goto next_srv;
6804 }
6805
6806 if (curproxy != px &&
6807 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6808 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6809 "tracking: disable-on-404 option inconsistency.\n",
6810 proxy_type_str(curproxy), curproxy->id,
6811 newsrv->id, px->id, srv->id);
6812 cfgerr++;
6813 goto next_srv;
6814 }
6815
6816 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006817 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006818 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006819 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006820 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006821 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006822 }
6823
6824 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006825 newsrv->tracknext = srv->trackers;
6826 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006827
6828 free(newsrv->trackit);
6829 newsrv->trackit = NULL;
6830 }
6831 next_srv:
6832 newsrv = newsrv->next;
6833 }
6834
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006835 /* We have to initialize the server lookup mechanism depending
6836 * on what LB algorithm was choosen.
6837 */
6838
6839 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6840 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6841 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006842 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6843 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6844 init_server_map(curproxy);
6845 } else {
6846 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6847 fwrr_init_server_groups(curproxy);
6848 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006849 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006850
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006851 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006852 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6853 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6854 fwlc_init_server_tree(curproxy);
6855 } else {
6856 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6857 fas_init_server_tree(curproxy);
6858 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006859 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006860
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006861 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006862 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6863 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6864 chash_init_server_tree(curproxy);
6865 } else {
6866 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6867 init_server_map(curproxy);
6868 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006869 break;
6870 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006871
6872 if (curproxy->options & PR_O_LOGASAP)
6873 curproxy->to_log &= ~LW_BYTES;
6874
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006875 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006876 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006877 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6878 proxy_type_str(curproxy), curproxy->id);
6879 err_code |= ERR_WARN;
6880 }
6881
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006882 if (curproxy->mode != PR_MODE_HTTP) {
6883 int optnum;
6884
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006885 if (curproxy->uri_auth) {
6886 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6887 proxy_type_str(curproxy), curproxy->id);
6888 err_code |= ERR_WARN;
6889 curproxy->uri_auth = NULL;
6890 }
6891
Willy Tarreau87cf5142011-08-19 22:57:24 +02006892 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006893 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6894 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6895 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006896 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006897 }
6898
6899 if (curproxy->options & PR_O_ORGTO) {
6900 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6901 "originalto", proxy_type_str(curproxy), curproxy->id);
6902 err_code |= ERR_WARN;
6903 curproxy->options &= ~PR_O_ORGTO;
6904 }
6905
6906 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6907 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6908 (curproxy->cap & cfg_opts[optnum].cap) &&
6909 (curproxy->options & cfg_opts[optnum].val)) {
6910 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6911 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6912 err_code |= ERR_WARN;
6913 curproxy->options &= ~cfg_opts[optnum].val;
6914 }
6915 }
6916
6917 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6918 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6919 (curproxy->cap & cfg_opts2[optnum].cap) &&
6920 (curproxy->options2 & cfg_opts2[optnum].val)) {
6921 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6922 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6923 err_code |= ERR_WARN;
6924 curproxy->options2 &= ~cfg_opts2[optnum].val;
6925 }
6926 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006927
Pieter Baauwd551fb52013-05-08 22:49:23 +02006928#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006929 if (curproxy->conn_src.bind_hdr_occ) {
6930 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006931 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006932 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006933 err_code |= ERR_WARN;
6934 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006935#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006936 }
6937
Willy Tarreaubaaee002006-06-26 02:48:02 +02006938 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006939 * ensure that we're not cross-dressing a TCP server into HTTP.
6940 */
6941 newsrv = curproxy->srv;
6942 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006943 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006944 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6945 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006946 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006947 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006948
Willy Tarreau0cec3312011-10-31 13:49:26 +01006949 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6950 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6951 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6952 err_code |= ERR_WARN;
6953 }
6954
Willy Tarreauc93cd162014-05-13 15:54:22 +02006955 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02006956 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6957 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6958 err_code |= ERR_WARN;
6959 }
6960
Pieter Baauwd551fb52013-05-08 22:49:23 +02006961#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006962 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6963 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006964 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 +01006965 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006966 err_code |= ERR_WARN;
6967 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006968#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006969 newsrv = newsrv->next;
6970 }
6971
Willy Tarreauc1a21672009-08-16 22:37:44 +02006972 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006973 if (!curproxy->accept)
6974 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006975
Willy Tarreauc1a21672009-08-16 22:37:44 +02006976 if (curproxy->tcp_req.inspect_delay ||
6977 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006978 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006979
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006980 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006981 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006982 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006983 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006984
6985 /* both TCP and HTTP must check switching rules */
6986 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6987 }
6988
6989 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006990 if (curproxy->tcp_req.inspect_delay ||
6991 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6992 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6993
Emeric Brun97679e72010-09-23 17:56:44 +02006994 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6995 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6996
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006997 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006998 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006999 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007000 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007001
7002 /* If the backend does requires RDP cookie persistence, we have to
7003 * enable the corresponding analyser.
7004 */
7005 if (curproxy->options2 & PR_O2_RDPC_PRST)
7006 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7007 }
7008
Emeric Brunc52962f2012-11-15 18:28:02 +01007009#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007010 /* Configure SSL for each bind line.
7011 * Note: if configuration fails at some point, the ->ctx member
7012 * remains NULL so that listeners can later detach.
7013 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007014 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007015 int alloc_ctx;
7016
Emeric Brunc52962f2012-11-15 18:28:02 +01007017 if (!bind_conf->is_ssl) {
7018 if (bind_conf->default_ctx) {
7019 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7020 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7021 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007022 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007023 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007024 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007025 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007026 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007027 cfgerr++;
7028 continue;
7029 }
7030
Emeric Brun8dc60392014-05-09 13:52:00 +02007031 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007032 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007033 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7034 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");
7035 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007036 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007037 cfgerr++;
7038 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007039 }
7040
Emeric Brunfc0421f2012-09-07 17:30:07 +02007041 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007042 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007043 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007044#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007045
Willy Tarreaue6b98942007-10-29 01:09:36 +01007046 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007047 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007048 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007049 if (!listener->luid) {
7050 /* listener ID not set, use automatic numbering with first
7051 * spare entry starting with next_luid.
7052 */
7053 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7054 listener->conf.id.key = listener->luid = next_id;
7055 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007056 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007057 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007058
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007059 /* enable separate counters */
7060 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7061 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007062 if (!listener->name)
7063 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007064 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007065
Willy Tarreaue6b98942007-10-29 01:09:36 +01007066 if (curproxy->options & PR_O_TCP_NOLING)
7067 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007068 if (!listener->maxconn)
7069 listener->maxconn = curproxy->maxconn;
7070 if (!listener->backlog)
7071 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007072 if (!listener->maxaccept)
7073 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7074
7075 /* we want to have an optimal behaviour on single process mode to
7076 * maximize the work at once, but in multi-process we want to keep
7077 * some fairness between processes, so we target half of the max
7078 * number of events to be balanced over all the processes the proxy
7079 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7080 * used to disable the limit.
7081 */
7082 if (listener->maxaccept > 0) {
7083 if (nbproc > 1)
7084 listener->maxaccept = (listener->maxaccept + 1) / 2;
7085 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7086 }
7087
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007088 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007089 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007090 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007091 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007092
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007093 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7094 listener->options |= LI_O_TCP_RULES;
7095
Willy Tarreaude3041d2010-05-31 10:56:17 +02007096 if (curproxy->mon_mask.s_addr)
7097 listener->options |= LI_O_CHK_MONNET;
7098
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007099 /* smart accept mode is automatic in HTTP mode */
7100 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007101 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007102 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7103 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007104 }
7105
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007106 /* Release unused SSL configs */
7107 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7108 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007109 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007110#ifdef USE_OPENSSL
7111 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007112 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007113 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007114 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007115 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007116#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007117 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007118
Willy Tarreau102df612014-05-07 23:56:38 +02007119 if (nbproc > 1) {
7120 if (curproxy->uri_auth) {
7121 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7122 curproxy->id);
7123 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7124 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7125 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007126 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007127 }
Willy Tarreau102df612014-05-07 23:56:38 +02007128 if (curproxy->appsession_name) {
7129 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7130 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007131 }
Willy Tarreau102df612014-05-07 23:56:38 +02007132 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7133 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7134 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007135 }
7136 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007137
7138 /* create the task associated with the proxy */
7139 curproxy->task = task_new();
7140 if (curproxy->task) {
7141 curproxy->task->context = curproxy;
7142 curproxy->task->process = manage_proxy;
7143 /* no need to queue, it will be done automatically if some
7144 * listener gets limited.
7145 */
7146 curproxy->task->expire = TICK_ETERNITY;
7147 } else {
7148 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7149 curproxy->id);
7150 cfgerr++;
7151 }
7152
Willy Tarreaubaaee002006-06-26 02:48:02 +02007153 curproxy = curproxy->next;
7154 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007155
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007156 /* Check multi-process mode compatibility */
Willy Tarreau4e5ed292014-05-13 13:37:54 +02007157 if (global.nbproc > 1 && global.stats_fe) {
Willy Tarreau67c2abc2014-05-09 18:48:46 +02007158 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7159 unsigned long mask;
7160
7161 mask = nbits(global.nbproc);
7162 if (global.stats_fe->bind_proc)
7163 mask &= global.stats_fe->bind_proc;
7164
7165 if (bind_conf->bind_proc)
7166 mask &= bind_conf->bind_proc;
7167
7168 /* stop here if more than one process is used */
7169 if (popcount(mask) > 1)
7170 break;
7171 }
7172 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7173 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");
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007174 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007175 }
7176
Willy Tarreau5436afc2014-09-16 12:17:36 +02007177 /* At this point, target names have already been resolved */
7178 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7179 if (curproxy->cap & PR_CAP_FE)
7180 propagate_processes(curproxy, NULL);
7181 }
7182
Willy Tarreaufbb78422011-06-05 15:38:35 +02007183 /* automatically compute fullconn if not set. We must not do it in the
7184 * loop above because cross-references are not yet fully resolved.
7185 */
7186 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7187 /* If <fullconn> is not set, let's set it to 10% of the sum of
7188 * the possible incoming frontend's maxconns.
7189 */
7190 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7191 struct proxy *fe;
7192 int total = 0;
7193
7194 /* sum up the number of maxconns of frontends which
7195 * reference this backend at least once or which are
7196 * the same one ('listen').
7197 */
7198 for (fe = proxy; fe; fe = fe->next) {
7199 struct switching_rule *rule;
7200 struct hdr_exp *exp;
7201 int found = 0;
7202
7203 if (!(fe->cap & PR_CAP_FE))
7204 continue;
7205
7206 if (fe == curproxy) /* we're on a "listen" instance */
7207 found = 1;
7208
7209 if (fe->defbe.be == curproxy) /* "default_backend" */
7210 found = 1;
7211
7212 /* check if a "use_backend" rule matches */
7213 if (!found) {
7214 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007215 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007216 found = 1;
7217 break;
7218 }
7219 }
7220 }
7221
7222 /* check if a "reqsetbe" rule matches */
7223 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7224 if (exp->action == ACT_SETBE &&
7225 (struct proxy *)exp->replace == curproxy) {
7226 found = 1;
7227 break;
7228 }
7229 }
7230
7231 /* now we've checked all possible ways to reference a backend
7232 * from a frontend.
7233 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007234 if (!found)
7235 continue;
7236 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007237 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007238 /* we have the sum of the maxconns in <total>. We only
7239 * keep 10% of that sum to set the default fullconn, with
7240 * a hard minimum of 1 (to avoid a divide by zero).
7241 */
7242 curproxy->fullconn = (total + 9) / 10;
7243 if (!curproxy->fullconn)
7244 curproxy->fullconn = 1;
7245 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007246 }
7247
Willy Tarreau056f5682010-06-06 15:51:11 +02007248 /* initialize stick-tables on backend capable proxies. This must not
7249 * be done earlier because the data size may be discovered while parsing
7250 * other proxies.
7251 */
Godbach9703e662013-12-11 21:11:41 +08007252 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007253 if (curproxy->state == PR_STSTOPPED)
7254 continue;
7255
Godbach9703e662013-12-11 21:11:41 +08007256 if (!stktable_init(&curproxy->table)) {
7257 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7258 cfgerr++;
7259 }
7260 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007261
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007262 /*
7263 * Recount currently required checks.
7264 */
7265
7266 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7267 int optnum;
7268
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007269 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7270 if (curproxy->options & cfg_opts[optnum].val)
7271 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007272
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007273 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7274 if (curproxy->options2 & cfg_opts2[optnum].val)
7275 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007276 }
7277
Willy Tarreau122541c2011-09-07 21:24:49 +02007278 if (peers) {
7279 struct peers *curpeers = peers, **last;
7280 struct peer *p, *pb;
7281
7282 /* Remove all peers sections which don't have a valid listener.
7283 * This can happen when a peers section is never referenced and
7284 * does not contain a local peer.
7285 */
7286 last = &peers;
7287 while (*last) {
7288 curpeers = *last;
7289 if (curpeers->peers_fe) {
7290 last = &curpeers->next;
7291 continue;
7292 }
7293
7294 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7295 curpeers->id, localpeer);
7296
7297 p = curpeers->remote;
7298 while (p) {
7299 pb = p->next;
7300 free(p->id);
7301 free(p);
7302 p = pb;
7303 }
7304
7305 /* Destroy and unlink this curpeers section.
7306 * Note: curpeers is backed up into *last.
7307 */
7308 free(curpeers->id);
7309 curpeers = curpeers->next;
7310 free(*last);
7311 *last = curpeers;
7312 }
7313 }
7314
Willy Tarreau34eb6712011-10-24 18:15:04 +02007315 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007316 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007317 MEM_F_SHARED);
7318
Willy Tarreaubb925012009-07-23 13:36:36 +02007319 if (cfgerr > 0)
7320 err_code |= ERR_ALERT | ERR_FATAL;
7321 out:
7322 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007323}
7324
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007325/*
7326 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7327 * parsing sessions.
7328 */
7329void cfg_register_keywords(struct cfg_kw_list *kwl)
7330{
7331 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7332}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007333
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007334/*
7335 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7336 */
7337void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7338{
7339 LIST_DEL(&kwl->list);
7340 LIST_INIT(&kwl->list);
7341}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007342
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007343/* this function register new section in the haproxy configuration file.
7344 * <section_name> is the name of this new section and <section_parser>
7345 * is the called parser. If two section declaration have the same name,
7346 * only the first declared is used.
7347 */
7348int cfg_register_section(char *section_name,
7349 int (*section_parser)(const char *, int, char **, int))
7350{
7351 struct cfg_section *cs;
7352
7353 cs = calloc(1, sizeof(*cs));
7354 if (!cs) {
7355 Alert("register section '%s': out of memory.\n", section_name);
7356 return 0;
7357 }
7358
7359 cs->section_name = section_name;
7360 cs->section_parser = section_parser;
7361
7362 LIST_ADDQ(&sections, &cs->list);
7363
7364 return 1;
7365}
7366
Willy Tarreaubaaee002006-06-26 02:48:02 +02007367/*
7368 * Local variables:
7369 * c-indent-level: 8
7370 * c-basic-offset: 8
7371 * End:
7372 */