blob: 5668393751811b90b0055b2ab9a04a4ca0a30197 [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 Tarreau91b00c22014-09-16 13:41:21 +02006045 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
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 Tarreau53fb4ae2009-10-04 23:04:08 +02006050 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006051 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006052
Willy Tarreau050536d2012-10-04 08:47:34 +02006053 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006054 /* proxy ID not set, use automatic numbering with first
6055 * spare entry starting with next_pxid.
6056 */
6057 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6058 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6059 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006060 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006061 next_pxid++;
6062
Willy Tarreau55ea7572007-06-17 19:56:27 +02006063
Willy Tarreaubaaee002006-06-26 02:48:02 +02006064 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006065 /* ensure we don't keep listeners uselessly bound */
6066 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006067 curproxy = curproxy->next;
6068 continue;
6069 }
6070
Willy Tarreau102df612014-05-07 23:56:38 +02006071 /* Check multi-process mode compatibility for the current proxy */
6072
6073 if (curproxy->bind_proc) {
6074 /* an explicit bind-process was specified, let's check how many
6075 * processes remain.
6076 */
6077 nbproc = popcount(curproxy->bind_proc);
6078
6079 curproxy->bind_proc &= nbits(global.nbproc);
6080 if (!curproxy->bind_proc && nbproc == 1) {
6081 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);
6082 curproxy->bind_proc = 1;
6083 }
6084 else if (!curproxy->bind_proc && nbproc > 1) {
6085 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);
6086 curproxy->bind_proc = 0;
6087 }
6088 }
6089
Willy Tarreau3d209582014-05-09 17:06:11 +02006090 /* check and reduce the bind-proc of each listener */
6091 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6092 unsigned long mask;
6093
6094 if (!bind_conf->bind_proc)
6095 continue;
6096
6097 mask = nbits(global.nbproc);
6098 if (curproxy->bind_proc)
6099 mask &= curproxy->bind_proc;
6100 /* mask cannot be null here thanks to the previous checks */
6101
6102 nbproc = popcount(bind_conf->bind_proc);
6103 bind_conf->bind_proc &= mask;
6104
6105 if (!bind_conf->bind_proc && nbproc == 1) {
6106 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",
6107 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6108 bind_conf->bind_proc = mask & ~(mask - 1);
6109 }
6110 else if (!bind_conf->bind_proc && nbproc > 1) {
6111 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",
6112 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6113 bind_conf->bind_proc = 0;
6114 }
6115 }
6116
Willy Tarreau102df612014-05-07 23:56:38 +02006117 if (global.nbproc > 1 && curproxy->table.peers.name) {
6118 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6119 curproxy->id);
6120 cfgerr++;
6121 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006122
Willy Tarreauff01a212009-03-15 13:46:16 +01006123 switch (curproxy->mode) {
6124 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006125 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006126 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006127 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6128 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006129 cfgerr++;
6130 }
6131
6132 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006133 Warning("config : servers will be ignored for %s '%s'.\n",
6134 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006135 break;
6136
6137 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006138 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006139 break;
6140
6141 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006142 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006143 break;
6144 }
6145
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006146 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006147 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006148 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006149 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6150 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006151 cfgerr++;
6152 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006153#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006154 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006155 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6156 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006157 cfgerr++;
6158 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006159#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006160 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006161 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6162 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006163 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006164 }
6165 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006166 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006167 /* If no LB algo is set in a backend, and we're not in
6168 * transparent mode, dispatch mode nor proxy mode, we
6169 * want to use balance roundrobin by default.
6170 */
6171 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6172 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006173 }
6174 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006175
Willy Tarreau1620ec32011-08-06 17:05:02 +02006176 if (curproxy->options & PR_O_DISPATCH)
6177 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6178 else if (curproxy->options & PR_O_HTTP_PROXY)
6179 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6180 else if (curproxy->options & PR_O_TRANSP)
6181 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006182
Willy Tarreau1620ec32011-08-06 17:05:02 +02006183 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6184 if (curproxy->options & PR_O_DISABLE404) {
6185 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6186 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6187 err_code |= ERR_WARN;
6188 curproxy->options &= ~PR_O_DISABLE404;
6189 }
6190 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6191 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6192 "send-state", proxy_type_str(curproxy), curproxy->id);
6193 err_code |= ERR_WARN;
6194 curproxy->options &= ~PR_O2_CHK_SNDST;
6195 }
Willy Tarreauef781042010-01-27 11:53:01 +01006196 }
6197
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006198 /* if a default backend was specified, let's find it */
6199 if (curproxy->defbe.name) {
6200 struct proxy *target;
6201
Alex Williams96532db2009-11-01 21:27:13 -05006202 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006203 if (!target) {
6204 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6205 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006206 cfgerr++;
6207 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006208 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6209 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006210 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006211 } else {
6212 free(curproxy->defbe.name);
6213 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006214
6215 /* Emit a warning if this proxy also has some servers */
6216 if (curproxy->srv) {
6217 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6218 curproxy->id);
6219 err_code |= ERR_WARN;
6220 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006221 }
6222 }
6223
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006224 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006225 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6226 /* map jump target for ACT_SETBE in req_rep chain */
6227 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006228 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006229 struct proxy *target;
6230
Willy Tarreaua496b602006-12-17 23:15:24 +01006231 if (exp->action != ACT_SETBE)
6232 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006233
Alex Williams96532db2009-11-01 21:27:13 -05006234 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006235 if (!target) {
6236 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6237 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006238 cfgerr++;
6239 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006240 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6241 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006242 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006243 } else {
6244 free((void *)exp->replace);
6245 exp->replace = (const char *)target;
6246 }
6247 }
6248 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006249
6250 /* find the target proxy for 'use_backend' rules */
6251 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006252 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006253 struct logformat_node *node;
6254 char *pxname;
6255
6256 /* Try to parse the string as a log format expression. If the result
6257 * of the parsing is only one entry containing a simple string, then
6258 * it's a standard string corresponding to a static rule, thus the
6259 * parsing is cancelled and be.name is restored to be resolved.
6260 */
6261 pxname = rule->be.name;
6262 LIST_INIT(&rule->be.expr);
6263 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6264 curproxy->conf.args.file, curproxy->conf.args.line);
6265 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6266
6267 if (!LIST_ISEMPTY(&rule->be.expr)) {
6268 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6269 rule->dynamic = 1;
6270 free(pxname);
6271 continue;
6272 }
6273 /* simple string: free the expression and fall back to static rule */
6274 free(node->arg);
6275 free(node);
6276 }
6277
6278 rule->dynamic = 0;
6279 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006280
Alex Williams96532db2009-11-01 21:27:13 -05006281 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006282
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006283 if (!target) {
6284 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6285 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006286 cfgerr++;
6287 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006288 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6289 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006290 cfgerr++;
6291 } else {
6292 free((void *)rule->be.name);
6293 rule->be.backend = target;
6294 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006295 }
6296
Willy Tarreau5436afc2014-09-16 12:17:36 +02006297 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006298 list_for_each_entry(srule, &curproxy->server_rules, list) {
6299 struct server *target = findserver(curproxy, srule->srv.name);
6300
6301 if (!target) {
6302 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6303 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6304 cfgerr++;
6305 continue;
6306 }
6307 free((void *)srule->srv.name);
6308 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006309 }
6310
Emeric Brunb982a3d2010-01-04 15:45:53 +01006311 /* find the target table for 'stick' rules */
6312 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6313 struct proxy *target;
6314
Emeric Brun1d33b292010-01-04 15:47:17 +01006315 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6316 if (mrule->flags & STK_IS_STORE)
6317 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6318
Emeric Brunb982a3d2010-01-04 15:45:53 +01006319 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006320 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006321 else
6322 target = curproxy;
6323
6324 if (!target) {
6325 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6326 curproxy->id, mrule->table.name);
6327 cfgerr++;
6328 }
6329 else if (target->table.size == 0) {
6330 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6331 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6332 cfgerr++;
6333 }
Willy Tarreau12785782012-04-27 21:37:17 +02006334 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6335 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006336 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6337 cfgerr++;
6338 }
6339 else {
6340 free((void *)mrule->table.name);
6341 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006342 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006343 }
6344 }
6345
6346 /* find the target table for 'store response' rules */
6347 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6348 struct proxy *target;
6349
Emeric Brun1d33b292010-01-04 15:47:17 +01006350 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6351
Emeric Brunb982a3d2010-01-04 15:45:53 +01006352 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006353 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006354 else
6355 target = curproxy;
6356
6357 if (!target) {
6358 Alert("Proxy '%s': unable to find store table '%s'.\n",
6359 curproxy->id, mrule->table.name);
6360 cfgerr++;
6361 }
6362 else if (target->table.size == 0) {
6363 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6364 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6365 cfgerr++;
6366 }
Willy Tarreau12785782012-04-27 21:37:17 +02006367 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6368 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006369 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6370 cfgerr++;
6371 }
6372 else {
6373 free((void *)mrule->table.name);
6374 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006375 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006376 }
6377 }
6378
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006379 /* find the target table for 'tcp-request' layer 4 rules */
6380 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6381 struct proxy *target;
6382
Willy Tarreaub4c84932013-07-23 19:15:30 +02006383 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006384 continue;
6385
6386 if (trule->act_prm.trk_ctr.table.n)
6387 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6388 else
6389 target = curproxy;
6390
6391 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006392 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6393 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006394 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006395 cfgerr++;
6396 }
6397 else if (target->table.size == 0) {
6398 Alert("Proxy '%s': table '%s' used but not configured.\n",
6399 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6400 cfgerr++;
6401 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006402 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6403 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6404 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 +01006405 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006406 cfgerr++;
6407 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006408 else {
6409 free(trule->act_prm.trk_ctr.table.n);
6410 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006411 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006412 * to pass a list of counters to track and allocate them right here using
6413 * stktable_alloc_data_type().
6414 */
6415 }
6416 }
6417
Willy Tarreaud1f96522010-08-03 19:34:32 +02006418 /* find the target table for 'tcp-request' layer 6 rules */
6419 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6420 struct proxy *target;
6421
Willy Tarreaub4c84932013-07-23 19:15:30 +02006422 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006423 continue;
6424
6425 if (trule->act_prm.trk_ctr.table.n)
6426 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6427 else
6428 target = curproxy;
6429
6430 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006431 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6432 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006433 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006434 cfgerr++;
6435 }
6436 else if (target->table.size == 0) {
6437 Alert("Proxy '%s': table '%s' used but not configured.\n",
6438 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6439 cfgerr++;
6440 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006441 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6442 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6443 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 +01006444 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006445 cfgerr++;
6446 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006447 else {
6448 free(trule->act_prm.trk_ctr.table.n);
6449 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006450 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006451 * to pass a list of counters to track and allocate them right here using
6452 * stktable_alloc_data_type().
6453 */
6454 }
6455 }
6456
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006457 /* move any "block" rules at the beginning of the http-request rules */
6458 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6459 /* insert block_rules into http_req_rules at the beginning */
6460 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6461 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6462 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6463 curproxy->http_req_rules.n = curproxy->block_rules.n;
6464 LIST_INIT(&curproxy->block_rules);
6465 }
6466
Emeric Brun32da3c42010-09-23 18:39:19 +02006467 if (curproxy->table.peers.name) {
6468 struct peers *curpeers = peers;
6469
6470 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6471 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6472 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006473 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006474 break;
6475 }
6476 }
6477
6478 if (!curpeers) {
6479 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6480 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006481 free((void *)curproxy->table.peers.name);
6482 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006483 cfgerr++;
6484 }
6485 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006486 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6487 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006488 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006489 cfgerr++;
6490 }
6491 }
6492
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006493 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006494 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006495 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6496 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6497 "proxy", curproxy->id);
6498 cfgerr++;
6499 goto out_uri_auth_compat;
6500 }
6501
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006502 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006503 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006504 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006505 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006506
Willy Tarreau95fa4692010-02-01 13:05:50 +01006507 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6508 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006509
6510 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006511 uri_auth_compat_req[i++] = "realm";
6512 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6513 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006514
Willy Tarreau95fa4692010-02-01 13:05:50 +01006515 uri_auth_compat_req[i++] = "unless";
6516 uri_auth_compat_req[i++] = "{";
6517 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6518 uri_auth_compat_req[i++] = "}";
6519 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006520
Willy Tarreauff011f22011-01-06 17:51:27 +01006521 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6522 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006523 cfgerr++;
6524 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006525 }
6526
Willy Tarreauff011f22011-01-06 17:51:27 +01006527 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006528
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006529 if (curproxy->uri_auth->auth_realm) {
6530 free(curproxy->uri_auth->auth_realm);
6531 curproxy->uri_auth->auth_realm = NULL;
6532 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006533
6534 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006535 }
6536out_uri_auth_compat:
6537
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006538 /* compile the log format */
6539 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006540 if (curproxy->conf.logformat_string != default_http_log_format &&
6541 curproxy->conf.logformat_string != default_tcp_log_format &&
6542 curproxy->conf.logformat_string != clf_http_log_format)
6543 free(curproxy->conf.logformat_string);
6544 curproxy->conf.logformat_string = NULL;
6545 free(curproxy->conf.lfs_file);
6546 curproxy->conf.lfs_file = NULL;
6547 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006548 }
6549
Willy Tarreau62a61232013-04-12 18:13:46 +02006550 if (curproxy->conf.logformat_string) {
6551 curproxy->conf.args.ctx = ARGC_LOG;
6552 curproxy->conf.args.file = curproxy->conf.lfs_file;
6553 curproxy->conf.args.line = curproxy->conf.lfs_line;
6554 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006555 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006556 curproxy->conf.args.file = NULL;
6557 curproxy->conf.args.line = 0;
6558 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006559
Willy Tarreau62a61232013-04-12 18:13:46 +02006560 if (curproxy->conf.uniqueid_format_string) {
6561 curproxy->conf.args.ctx = ARGC_UIF;
6562 curproxy->conf.args.file = curproxy->conf.uif_file;
6563 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006564 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006565 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6566 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006567 curproxy->conf.args.file = NULL;
6568 curproxy->conf.args.line = 0;
6569 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006570
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006571 /* only now we can check if some args remain unresolved.
6572 * This must be done after the users and groups resolution.
6573 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006574 cfgerr += smp_resolve_args(curproxy);
6575 if (!cfgerr)
6576 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006577
Willy Tarreau2738a142006-07-08 17:28:09 +02006578 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006579 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006580 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006581 (!curproxy->timeout.connect ||
6582 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006583 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006584 " | While not properly invalid, you will certainly encounter various problems\n"
6585 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006586 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006587 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006588 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006589 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006590
Willy Tarreau1fa31262007-12-03 00:36:16 +01006591 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6592 * We must still support older configurations, so let's find out whether those
6593 * parameters have been set or must be copied from contimeouts.
6594 */
6595 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006596 if (!curproxy->timeout.tarpit ||
6597 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006598 /* tarpit timeout not set. We search in the following order:
6599 * default.tarpit, curr.connect, default.connect.
6600 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006601 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006602 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006603 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006604 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006605 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006606 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006607 }
6608 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006609 (!curproxy->timeout.queue ||
6610 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006611 /* queue timeout not set. We search in the following order:
6612 * default.queue, curr.connect, default.connect.
6613 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006614 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006615 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006616 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006617 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006618 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006619 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006620 }
6621 }
6622
Willy Tarreau1620ec32011-08-06 17:05:02 +02006623 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006624 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6625 curproxy->check_req = (char *)malloc(curproxy->check_len);
6626 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006627 }
6628
Willy Tarreau215663d2014-06-13 18:30:23 +02006629 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6630 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6631 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6632 proxy_type_str(curproxy), curproxy->id);
6633 err_code |= ERR_WARN;
6634 }
6635
Willy Tarreau193b8c62012-11-22 00:17:38 +01006636 /* ensure that cookie capture length is not too large */
6637 if (curproxy->capture_len >= global.tune.cookie_len) {
6638 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6639 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6640 err_code |= ERR_WARN;
6641 curproxy->capture_len = global.tune.cookie_len - 1;
6642 }
6643
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006644 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006645 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006646 curproxy->req_cap_pool = create_pool("ptrcap",
6647 curproxy->nb_req_cap * sizeof(char *),
6648 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006649 }
6650
6651 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006652 curproxy->rsp_cap_pool = create_pool("ptrcap",
6653 curproxy->nb_rsp_cap * sizeof(char *),
6654 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006655 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006656
Willy Tarreaubaaee002006-06-26 02:48:02 +02006657 /* first, we will invert the servers list order */
6658 newsrv = NULL;
6659 while (curproxy->srv) {
6660 struct server *next;
6661
6662 next = curproxy->srv->next;
6663 curproxy->srv->next = newsrv;
6664 newsrv = curproxy->srv;
6665 if (!next)
6666 break;
6667 curproxy->srv = next;
6668 }
6669
Willy Tarreau17edc812014-01-03 12:14:34 +01006670 /* Check that no server name conflicts. This causes trouble in the stats.
6671 * We only emit a warning for the first conflict affecting each server,
6672 * in order to avoid combinatory explosion if all servers have the same
6673 * name. We do that only for servers which do not have an explicit ID,
6674 * because these IDs were made also for distinguishing them and we don't
6675 * want to annoy people who correctly manage them.
6676 */
6677 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6678 struct server *other_srv;
6679
6680 if (newsrv->puid)
6681 continue;
6682
6683 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6684 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6685 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6686 newsrv->conf.file, newsrv->conf.line,
6687 proxy_type_str(curproxy), curproxy->id,
6688 newsrv->id, other_srv->conf.line);
6689 break;
6690 }
6691 }
6692 }
6693
Willy Tarreaudd701652010-05-25 23:03:02 +02006694 /* assign automatic UIDs to servers which don't have one yet */
6695 next_id = 1;
6696 newsrv = curproxy->srv;
6697 while (newsrv != NULL) {
6698 if (!newsrv->puid) {
6699 /* server ID not set, use automatic numbering with first
6700 * spare entry starting with next_svid.
6701 */
6702 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6703 newsrv->conf.id.key = newsrv->puid = next_id;
6704 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6705 }
6706 next_id++;
6707 newsrv = newsrv->next;
6708 }
6709
Willy Tarreau20697042007-11-15 23:26:18 +01006710 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006711 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006712
Willy Tarreau62c3be22012-01-20 13:12:32 +01006713 /*
6714 * If this server supports a maxconn parameter, it needs a dedicated
6715 * tasks to fill the emptied slots when a connection leaves.
6716 * Also, resolve deferred tracking dependency if needed.
6717 */
6718 newsrv = curproxy->srv;
6719 while (newsrv != NULL) {
6720 if (newsrv->minconn > newsrv->maxconn) {
6721 /* Only 'minconn' was specified, or it was higher than or equal
6722 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6723 * this will avoid further useless expensive computations.
6724 */
6725 newsrv->maxconn = newsrv->minconn;
6726 } else if (newsrv->maxconn && !newsrv->minconn) {
6727 /* minconn was not specified, so we set it to maxconn */
6728 newsrv->minconn = newsrv->maxconn;
6729 }
6730
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006731#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006732 if (newsrv->use_ssl || newsrv->check.use_ssl)
6733 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006734#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006735
Willy Tarreau2f075e92013-12-03 11:11:34 +01006736 /* set the check type on the server */
6737 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6738
Willy Tarreau62c3be22012-01-20 13:12:32 +01006739 if (newsrv->trackit) {
6740 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006741 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006742 char *pname, *sname;
6743
6744 pname = newsrv->trackit;
6745 sname = strrchr(pname, '/');
6746
6747 if (sname)
6748 *sname++ = '\0';
6749 else {
6750 sname = pname;
6751 pname = NULL;
6752 }
6753
6754 if (pname) {
6755 px = findproxy(pname, PR_CAP_BE);
6756 if (!px) {
6757 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6758 proxy_type_str(curproxy), curproxy->id,
6759 newsrv->id, pname);
6760 cfgerr++;
6761 goto next_srv;
6762 }
6763 } else
6764 px = curproxy;
6765
6766 srv = findserver(px, sname);
6767 if (!srv) {
6768 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6769 proxy_type_str(curproxy), curproxy->id,
6770 newsrv->id, sname);
6771 cfgerr++;
6772 goto next_srv;
6773 }
6774
Willy Tarreau32091232014-05-16 13:52:00 +02006775 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6776 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6777 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006778 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006779 "tracking as it does not have any check nor agent enabled.\n",
6780 proxy_type_str(curproxy), curproxy->id,
6781 newsrv->id, px->id, srv->id);
6782 cfgerr++;
6783 goto next_srv;
6784 }
6785
6786 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6787
6788 if (loop) {
6789 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6790 "belongs to a tracking chain looping back to %s/%s.\n",
6791 proxy_type_str(curproxy), curproxy->id,
6792 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006793 cfgerr++;
6794 goto next_srv;
6795 }
6796
6797 if (curproxy != px &&
6798 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6799 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6800 "tracking: disable-on-404 option inconsistency.\n",
6801 proxy_type_str(curproxy), curproxy->id,
6802 newsrv->id, px->id, srv->id);
6803 cfgerr++;
6804 goto next_srv;
6805 }
6806
6807 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006808 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006809 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006810 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006811 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006812 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006813 }
6814
6815 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006816 newsrv->tracknext = srv->trackers;
6817 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006818
6819 free(newsrv->trackit);
6820 newsrv->trackit = NULL;
6821 }
6822 next_srv:
6823 newsrv = newsrv->next;
6824 }
6825
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006826 /* We have to initialize the server lookup mechanism depending
6827 * on what LB algorithm was choosen.
6828 */
6829
6830 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6831 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6832 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006833 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6834 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6835 init_server_map(curproxy);
6836 } else {
6837 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6838 fwrr_init_server_groups(curproxy);
6839 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006840 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006841
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006842 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006843 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6844 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6845 fwlc_init_server_tree(curproxy);
6846 } else {
6847 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6848 fas_init_server_tree(curproxy);
6849 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006850 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006851
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006852 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006853 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6854 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6855 chash_init_server_tree(curproxy);
6856 } else {
6857 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6858 init_server_map(curproxy);
6859 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006860 break;
6861 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006862
6863 if (curproxy->options & PR_O_LOGASAP)
6864 curproxy->to_log &= ~LW_BYTES;
6865
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006866 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006867 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006868 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6869 proxy_type_str(curproxy), curproxy->id);
6870 err_code |= ERR_WARN;
6871 }
6872
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006873 if (curproxy->mode != PR_MODE_HTTP) {
6874 int optnum;
6875
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006876 if (curproxy->uri_auth) {
6877 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6878 proxy_type_str(curproxy), curproxy->id);
6879 err_code |= ERR_WARN;
6880 curproxy->uri_auth = NULL;
6881 }
6882
Willy Tarreau87cf5142011-08-19 22:57:24 +02006883 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006884 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6885 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6886 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006887 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006888 }
6889
6890 if (curproxy->options & PR_O_ORGTO) {
6891 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6892 "originalto", proxy_type_str(curproxy), curproxy->id);
6893 err_code |= ERR_WARN;
6894 curproxy->options &= ~PR_O_ORGTO;
6895 }
6896
6897 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6898 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6899 (curproxy->cap & cfg_opts[optnum].cap) &&
6900 (curproxy->options & cfg_opts[optnum].val)) {
6901 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6902 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6903 err_code |= ERR_WARN;
6904 curproxy->options &= ~cfg_opts[optnum].val;
6905 }
6906 }
6907
6908 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6909 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6910 (curproxy->cap & cfg_opts2[optnum].cap) &&
6911 (curproxy->options2 & cfg_opts2[optnum].val)) {
6912 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6913 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6914 err_code |= ERR_WARN;
6915 curproxy->options2 &= ~cfg_opts2[optnum].val;
6916 }
6917 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006918
Pieter Baauwd551fb52013-05-08 22:49:23 +02006919#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006920 if (curproxy->conn_src.bind_hdr_occ) {
6921 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006922 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006923 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006924 err_code |= ERR_WARN;
6925 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006926#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006927 }
6928
Willy Tarreaubaaee002006-06-26 02:48:02 +02006929 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006930 * ensure that we're not cross-dressing a TCP server into HTTP.
6931 */
6932 newsrv = curproxy->srv;
6933 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006934 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006935 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6936 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006937 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006938 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006939
Willy Tarreau0cec3312011-10-31 13:49:26 +01006940 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6941 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6942 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6943 err_code |= ERR_WARN;
6944 }
6945
Willy Tarreauc93cd162014-05-13 15:54:22 +02006946 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02006947 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6948 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6949 err_code |= ERR_WARN;
6950 }
6951
Pieter Baauwd551fb52013-05-08 22:49:23 +02006952#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006953 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6954 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006955 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 +01006956 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006957 err_code |= ERR_WARN;
6958 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006959#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006960 newsrv = newsrv->next;
6961 }
6962
Willy Tarreauc1a21672009-08-16 22:37:44 +02006963 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006964 if (!curproxy->accept)
6965 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006966
Willy Tarreauc1a21672009-08-16 22:37:44 +02006967 if (curproxy->tcp_req.inspect_delay ||
6968 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006969 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006970
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006971 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006972 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006973 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006974 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006975
6976 /* both TCP and HTTP must check switching rules */
6977 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6978 }
6979
6980 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006981 if (curproxy->tcp_req.inspect_delay ||
6982 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6983 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6984
Emeric Brun97679e72010-09-23 17:56:44 +02006985 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6986 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6987
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006988 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006989 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006990 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006991 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006992
6993 /* If the backend does requires RDP cookie persistence, we have to
6994 * enable the corresponding analyser.
6995 */
6996 if (curproxy->options2 & PR_O2_RDPC_PRST)
6997 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6998 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02006999 }
7000
7001 /***********************************************************/
7002 /* At this point, target names have already been resolved. */
7003 /***********************************************************/
7004
7005 /* Check multi-process mode compatibility */
7006
7007 if (global.nbproc > 1 && global.stats_fe) {
7008 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7009 unsigned long mask;
7010
7011 mask = nbits(global.nbproc);
7012 if (global.stats_fe->bind_proc)
7013 mask &= global.stats_fe->bind_proc;
7014
7015 if (bind_conf->bind_proc)
7016 mask &= bind_conf->bind_proc;
7017
7018 /* stop here if more than one process is used */
7019 if (popcount(mask) > 1)
7020 break;
7021 }
7022 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7023 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");
7024 }
7025 }
7026
7027 /* Make each frontend inherit bind-process from its listeners when not specified. */
7028 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7029 if (curproxy->bind_proc)
7030 continue;
7031
7032 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7033 unsigned long mask;
7034
7035 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7036 curproxy->bind_proc |= mask;
7037 }
7038
7039 if (!curproxy->bind_proc)
7040 curproxy->bind_proc = ~0UL;
7041 }
7042
7043 if (global.stats_fe) {
7044 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7045 unsigned long mask;
7046
7047 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7048 global.stats_fe->bind_proc |= mask;
7049 }
7050 if (!global.stats_fe->bind_proc)
7051 global.stats_fe->bind_proc = ~0UL;
7052 }
7053
7054 /* propagate bindings from frontends to backends */
7055 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7056 if (curproxy->cap & PR_CAP_FE)
7057 propagate_processes(curproxy, NULL);
7058 }
7059
7060 /* Bind each unbound backend to all processes when not specified. */
7061 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7062 if (curproxy->bind_proc)
7063 continue;
7064 curproxy->bind_proc = ~0UL;
7065 }
7066
7067 /*******************************************************/
7068 /* At this step, all proxies have a non-null bind_proc */
7069 /*******************************************************/
7070
7071 /* perform the final checks before creating tasks */
7072
7073 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7074 struct listener *listener;
7075 unsigned int next_id;
7076 int nbproc;
7077
7078 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007079
Emeric Brunc52962f2012-11-15 18:28:02 +01007080#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007081 /* Configure SSL for each bind line.
7082 * Note: if configuration fails at some point, the ->ctx member
7083 * remains NULL so that listeners can later detach.
7084 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007085 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007086 int alloc_ctx;
7087
Emeric Brunc52962f2012-11-15 18:28:02 +01007088 if (!bind_conf->is_ssl) {
7089 if (bind_conf->default_ctx) {
7090 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7091 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7092 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007093 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007094 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007095 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007096 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007097 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007098 cfgerr++;
7099 continue;
7100 }
7101
Emeric Brun8dc60392014-05-09 13:52:00 +02007102 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007103 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007104 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7105 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");
7106 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007107 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007108 cfgerr++;
7109 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007110 }
7111
Emeric Brunfc0421f2012-09-07 17:30:07 +02007112 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007113 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007114 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007115#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007116
Willy Tarreaue6b98942007-10-29 01:09:36 +01007117 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007118 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007119 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007120 if (!listener->luid) {
7121 /* listener ID not set, use automatic numbering with first
7122 * spare entry starting with next_luid.
7123 */
7124 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7125 listener->conf.id.key = listener->luid = next_id;
7126 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007127 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007128 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007129
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007130 /* enable separate counters */
7131 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7132 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007133 if (!listener->name)
7134 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007135 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007136
Willy Tarreaue6b98942007-10-29 01:09:36 +01007137 if (curproxy->options & PR_O_TCP_NOLING)
7138 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007139 if (!listener->maxconn)
7140 listener->maxconn = curproxy->maxconn;
7141 if (!listener->backlog)
7142 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007143 if (!listener->maxaccept)
7144 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7145
7146 /* we want to have an optimal behaviour on single process mode to
7147 * maximize the work at once, but in multi-process we want to keep
7148 * some fairness between processes, so we target half of the max
7149 * number of events to be balanced over all the processes the proxy
7150 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7151 * used to disable the limit.
7152 */
7153 if (listener->maxaccept > 0) {
7154 if (nbproc > 1)
7155 listener->maxaccept = (listener->maxaccept + 1) / 2;
7156 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7157 }
7158
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007159 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007160 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007161 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007162 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007163
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007164 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7165 listener->options |= LI_O_TCP_RULES;
7166
Willy Tarreaude3041d2010-05-31 10:56:17 +02007167 if (curproxy->mon_mask.s_addr)
7168 listener->options |= LI_O_CHK_MONNET;
7169
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007170 /* smart accept mode is automatic in HTTP mode */
7171 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007172 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007173 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7174 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007175 }
7176
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007177 /* Release unused SSL configs */
7178 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7179 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007180 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007181#ifdef USE_OPENSSL
7182 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007183 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007184 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007185 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007186 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007187#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007188 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007189
Willy Tarreau102df612014-05-07 23:56:38 +02007190 if (nbproc > 1) {
7191 if (curproxy->uri_auth) {
Willy Tarreau036a83e2014-09-16 15:11:04 +02007192 int count, maxproc = 0;
7193
7194 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7195 count = popcount(bind_conf->bind_proc);
7196 if (count > maxproc)
7197 maxproc = count;
7198 }
7199 /* backends have 0, frontends have 1 or more */
7200 if (maxproc != 1)
7201 Warning("Proxy '%s': in multi-process mode, stats will be"
7202 " limited to process assigned to the current request.\n",
7203 curproxy->id);
7204
Willy Tarreau102df612014-05-07 23:56:38 +02007205 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7206 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7207 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007208 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007209 }
Willy Tarreau102df612014-05-07 23:56:38 +02007210 if (curproxy->appsession_name) {
7211 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7212 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007213 }
Willy Tarreau102df612014-05-07 23:56:38 +02007214 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7215 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7216 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007217 }
7218 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007219
7220 /* create the task associated with the proxy */
7221 curproxy->task = task_new();
7222 if (curproxy->task) {
7223 curproxy->task->context = curproxy;
7224 curproxy->task->process = manage_proxy;
7225 /* no need to queue, it will be done automatically if some
7226 * listener gets limited.
7227 */
7228 curproxy->task->expire = TICK_ETERNITY;
7229 } else {
7230 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7231 curproxy->id);
7232 cfgerr++;
7233 }
Willy Tarreaue56c4f12014-09-16 13:21:03 +02007234 }
7235
Willy Tarreaufbb78422011-06-05 15:38:35 +02007236 /* automatically compute fullconn if not set. We must not do it in the
7237 * loop above because cross-references are not yet fully resolved.
7238 */
7239 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7240 /* If <fullconn> is not set, let's set it to 10% of the sum of
7241 * the possible incoming frontend's maxconns.
7242 */
7243 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7244 struct proxy *fe;
7245 int total = 0;
7246
7247 /* sum up the number of maxconns of frontends which
7248 * reference this backend at least once or which are
7249 * the same one ('listen').
7250 */
7251 for (fe = proxy; fe; fe = fe->next) {
7252 struct switching_rule *rule;
7253 struct hdr_exp *exp;
7254 int found = 0;
7255
7256 if (!(fe->cap & PR_CAP_FE))
7257 continue;
7258
7259 if (fe == curproxy) /* we're on a "listen" instance */
7260 found = 1;
7261
7262 if (fe->defbe.be == curproxy) /* "default_backend" */
7263 found = 1;
7264
7265 /* check if a "use_backend" rule matches */
7266 if (!found) {
7267 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007268 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007269 found = 1;
7270 break;
7271 }
7272 }
7273 }
7274
7275 /* check if a "reqsetbe" rule matches */
7276 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7277 if (exp->action == ACT_SETBE &&
7278 (struct proxy *)exp->replace == curproxy) {
7279 found = 1;
7280 break;
7281 }
7282 }
7283
7284 /* now we've checked all possible ways to reference a backend
7285 * from a frontend.
7286 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007287 if (!found)
7288 continue;
7289 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007290 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007291 /* we have the sum of the maxconns in <total>. We only
7292 * keep 10% of that sum to set the default fullconn, with
7293 * a hard minimum of 1 (to avoid a divide by zero).
7294 */
7295 curproxy->fullconn = (total + 9) / 10;
7296 if (!curproxy->fullconn)
7297 curproxy->fullconn = 1;
7298 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007299 }
7300
Willy Tarreau056f5682010-06-06 15:51:11 +02007301 /* initialize stick-tables on backend capable proxies. This must not
7302 * be done earlier because the data size may be discovered while parsing
7303 * other proxies.
7304 */
Godbach9703e662013-12-11 21:11:41 +08007305 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007306 if (curproxy->state == PR_STSTOPPED)
7307 continue;
7308
Godbach9703e662013-12-11 21:11:41 +08007309 if (!stktable_init(&curproxy->table)) {
7310 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7311 cfgerr++;
7312 }
7313 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007314
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007315 /*
7316 * Recount currently required checks.
7317 */
7318
7319 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7320 int optnum;
7321
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007322 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7323 if (curproxy->options & cfg_opts[optnum].val)
7324 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007325
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007326 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7327 if (curproxy->options2 & cfg_opts2[optnum].val)
7328 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007329 }
7330
Willy Tarreau122541c2011-09-07 21:24:49 +02007331 if (peers) {
7332 struct peers *curpeers = peers, **last;
7333 struct peer *p, *pb;
7334
7335 /* Remove all peers sections which don't have a valid listener.
7336 * This can happen when a peers section is never referenced and
7337 * does not contain a local peer.
7338 */
7339 last = &peers;
7340 while (*last) {
7341 curpeers = *last;
7342 if (curpeers->peers_fe) {
7343 last = &curpeers->next;
7344 continue;
7345 }
7346
7347 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7348 curpeers->id, localpeer);
7349
7350 p = curpeers->remote;
7351 while (p) {
7352 pb = p->next;
7353 free(p->id);
7354 free(p);
7355 p = pb;
7356 }
7357
7358 /* Destroy and unlink this curpeers section.
7359 * Note: curpeers is backed up into *last.
7360 */
7361 free(curpeers->id);
7362 curpeers = curpeers->next;
7363 free(*last);
7364 *last = curpeers;
7365 }
7366 }
7367
Willy Tarreau34eb6712011-10-24 18:15:04 +02007368 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007369 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007370 MEM_F_SHARED);
7371
Willy Tarreaubb925012009-07-23 13:36:36 +02007372 if (cfgerr > 0)
7373 err_code |= ERR_ALERT | ERR_FATAL;
7374 out:
7375 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007376}
7377
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007378/*
7379 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7380 * parsing sessions.
7381 */
7382void cfg_register_keywords(struct cfg_kw_list *kwl)
7383{
7384 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7385}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007386
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007387/*
7388 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7389 */
7390void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7391{
7392 LIST_DEL(&kwl->list);
7393 LIST_INIT(&kwl->list);
7394}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007395
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007396/* this function register new section in the haproxy configuration file.
7397 * <section_name> is the name of this new section and <section_parser>
7398 * is the called parser. If two section declaration have the same name,
7399 * only the first declared is used.
7400 */
7401int cfg_register_section(char *section_name,
7402 int (*section_parser)(const char *, int, char **, int))
7403{
7404 struct cfg_section *cs;
7405
7406 cs = calloc(1, sizeof(*cs));
7407 if (!cs) {
7408 Alert("register section '%s': out of memory.\n", section_name);
7409 return 0;
7410 }
7411
7412 cs->section_name = section_name;
7413 cs->section_parser = section_parser;
7414
7415 LIST_ADDQ(&sections, &cs->list);
7416
7417 return 1;
7418}
7419
Willy Tarreaubaaee002006-06-26 02:48:02 +02007420/*
7421 * Local variables:
7422 * c-indent-level: 8
7423 * c-basic-offset: 8
7424 * End:
7425 */