blob: 3e345e48c0e0f008d1e89e8055280bb173ccf708 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010049#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020050#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051
Willy Tarreaueb0c6142007-05-07 00:53:22 +020052#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010053#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020054#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020055#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020057#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020058#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020059#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020060#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020061#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010062#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020063#include <proto/lb_fwlc.h>
64#include <proto/lb_fwrr.h>
65#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020066#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020068#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010069#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020070#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010071#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010072#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020073#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020074#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020075#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010076#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020077#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020078#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010079#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020080
Emeric Brunfc0421f2012-09-07 17:30:07 +020081#ifdef USE_OPENSSL
82#include <types/ssl_sock.h>
83#include <proto/ssl_sock.h>
84#include <proto/shctx.h>
85#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020086
Willy Tarreauf3c69202006-07-09 16:42:34 +020087/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
88 * ssl-hello-chk option to ensure that the remote server speaks SSL.
89 *
90 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
91 */
92const char sslv3_client_hello_pkt[] = {
93 "\x16" /* ContentType : 0x16 = Hanshake */
94 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
95 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
96 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
97 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
98 "\x03\x00" /* Hello Version : 0x0300 = v3 */
99 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
100 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
101 "\x00" /* Session ID length : empty (no session ID) */
102 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
103 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
104 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
105 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
106 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
107 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
108 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
109 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
110 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
111 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
112 "\x00\x38" "\x00\x39" "\x00\x3A"
113 "\x01" /* Compression Length : 0x01 = 1 byte for types */
114 "\x00" /* Compression Type : 0x00 = NULL compression */
115};
116
Willy Tarreau3842f002009-06-14 11:39:52 +0200117/* various keyword modifiers */
118enum kw_mod {
119 KWM_STD = 0, /* normal */
120 KWM_NO, /* "no" prefixed before the keyword */
121 KWM_DEF, /* "default" prefixed before the keyword */
122};
123
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100124/* permit to store configuration section */
125struct cfg_section {
126 struct list list;
127 char *section_name;
128 int (*section_parser)(const char *, int, char **, int);
129};
130
131/* Used to chain configuration sections definitions. This list
132 * stores struct cfg_section
133 */
134struct list sections = LIST_HEAD_INIT(sections);
135
Willy Tarreau13943ab2006-12-31 00:24:10 +0100136/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100137struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138 const char *name;
139 unsigned int val;
140 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100141 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100142 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100143};
144
145/* proxy->options */
146static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100147{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
149 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
150 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
151 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
152 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
153 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100154 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100155 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
157 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
158 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
159 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
160 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100161#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100162 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100163#else
164 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100165#endif
166
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100167 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100168};
169
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100170/* proxy->options2 */
171static const struct cfg_opt cfg_opts2[] =
172{
173#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100174 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
175 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
176 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100177#else
178 { "splice-request", 0, 0, 0, 0 },
179 { "splice-response", 0, 0, 0, 0 },
180 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100181#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100182 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
183 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
184 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
185 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
186 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
187 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
188 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
189 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
190 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400191 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100192 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200193 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200194 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100195 { NULL, 0, 0, 0 }
196};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200197
Willy Tarreau6daf3432008-01-22 16:44:08 +0100198static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
200int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100201int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200203/* List head of all known configuration keywords */
204static struct cfg_kw_list cfg_keywords = {
205 .list = LIST_HEAD_INIT(cfg_keywords.list)
206};
207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208/*
209 * converts <str> to a list of listeners which are dynamically allocated.
210 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
211 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
212 * - <port> is a numerical port from 1 to 65535 ;
213 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
214 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200215 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
216 * not NULL, it must be a valid pointer to either NULL or a freeable area that
217 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200218 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219int 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 +0200220{
221 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100222 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 int port, end;
224
225 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200226
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100228 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100229 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
231 str = next;
232 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100233 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234 *next++ = 0;
235 }
236
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100237 ss2 = str2sa_range(str, &port, &end, err,
238 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
239 if (!ss2)
240 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100242 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100243 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200244 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100248 if (!port || !end) {
249 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
250 goto fail;
251 }
252
Emeric Bruned760922010-10-22 17:59:25 +0200253 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200254 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200255 goto fail;
256 }
257
258 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100263 else if (ss2->ss_family == AF_UNSPEC) {
264 socklen_t addr_len;
265
266 /* We want to attach to an already bound fd whose number
267 * is in the addr part of ss2 when cast to sockaddr_in.
268 * Note that by definition there is a single listener.
269 * We still have to determine the address family to
270 * register the correct protocol.
271 */
272 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
273 addr_len = sizeof(*ss2);
274 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
275 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
276 goto fail;
277 }
278
279 port = end = get_host_port(ss2);
280 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100282 /* OK the address looks correct */
283 ss = *ss2;
284
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285 for (; port <= end; port++) {
286 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100287 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200288 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
289 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
290 l->frontend = curproxy;
291 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292
Willy Tarreau40aa0702013-03-10 23:51:38 +0100293 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200295 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100296 l->state = LI_INIT;
297
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100298 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100300 tcpv4_add_listener(l);
301 }
Emeric Bruned760922010-10-22 17:59:25 +0200302 else if (ss.ss_family == AF_INET6) {
303 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
304 tcpv6_add_listener(l);
305 }
306 else {
Emeric Bruned760922010-10-22 17:59:25 +0200307 uxst_add_listener(l);
308 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200309
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200310 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100311 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200312 } /* end for(port) */
313 } /* end while(next) */
314 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200315 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200316 fail:
317 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319}
320
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200321/* Report a warning if a rule is placed after a 'tcp-request content' rule.
322 * Return 1 if the warning has been emitted, otherwise 0.
323 */
324int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
325{
326 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
327 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
328 file, line, arg);
329 return 1;
330 }
331 return 0;
332}
333
Willy Tarreau61d18892009-03-31 10:49:21 +0200334/* Report a warning if a rule is placed after a 'block' rule.
335 * Return 1 if the warning has been emitted, otherwise 0.
336 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100337int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200338{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200339 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200340 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
341 file, line, arg);
342 return 1;
343 }
344 return 0;
345}
346
Willy Tarreau5002f572014-04-23 01:32:02 +0200347/* Report a warning if a rule is placed after an 'http_request' rule.
348 * Return 1 if the warning has been emitted, otherwise 0.
349 */
350int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
351{
352 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
353 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
354 file, line, arg);
355 return 1;
356 }
357 return 0;
358}
359
Willy Tarreau61d18892009-03-31 10:49:21 +0200360/* Report a warning if a rule is placed after a reqrewrite rule.
361 * Return 1 if the warning has been emitted, otherwise 0.
362 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100363int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200364{
365 if (proxy->req_exp) {
366 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
367 file, line, arg);
368 return 1;
369 }
370 return 0;
371}
372
373/* Report a warning if a rule is placed after a reqadd rule.
374 * Return 1 if the warning has been emitted, otherwise 0.
375 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100376int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200377{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100378 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200379 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
380 file, line, arg);
381 return 1;
382 }
383 return 0;
384}
385
386/* Report a warning if a rule is placed after a redirect rule.
387 * Return 1 if the warning has been emitted, otherwise 0.
388 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100389int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200390{
391 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
392 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
393 file, line, arg);
394 return 1;
395 }
396 return 0;
397}
398
399/* Report a warning if a rule is placed after a 'use_backend' rule.
400 * Return 1 if the warning has been emitted, otherwise 0.
401 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
404 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
405 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
406 file, line, arg);
407 return 1;
408 }
409 return 0;
410}
411
Willy Tarreauee445d92014-04-23 01:39:04 +0200412/* Report a warning if a rule is placed after a 'use-server' rule.
413 * Return 1 if the warning has been emitted, otherwise 0.
414 */
415int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
416{
417 if (!LIST_ISEMPTY(&proxy->server_rules)) {
418 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
419 file, line, arg);
420 return 1;
421 }
422 return 0;
423}
424
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200425/* report a warning if a "tcp request connection" rule is dangerously placed */
426int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
427{
428 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
429 warnif_rule_after_block(proxy, file, line, arg) ||
430 warnif_rule_after_http_req(proxy, file, line, arg) ||
431 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
432 warnif_rule_after_reqadd(proxy, file, line, arg) ||
433 warnif_rule_after_redirect(proxy, file, line, arg) ||
434 warnif_rule_after_use_backend(proxy, file, line, arg) ||
435 warnif_rule_after_use_server(proxy, file, line, arg);
436}
437
438/* report a warning if a "tcp request content" rule is dangerously placed */
439int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
440{
441 return warnif_rule_after_block(proxy, file, line, arg) ||
442 warnif_rule_after_http_req(proxy, file, line, arg) ||
443 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
444 warnif_rule_after_reqadd(proxy, file, line, arg) ||
445 warnif_rule_after_redirect(proxy, file, line, arg) ||
446 warnif_rule_after_use_backend(proxy, file, line, arg) ||
447 warnif_rule_after_use_server(proxy, file, line, arg);
448}
449
Willy Tarreau61d18892009-03-31 10:49:21 +0200450/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100451int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200452{
Willy Tarreau5002f572014-04-23 01:32:02 +0200453 return warnif_rule_after_http_req(proxy, file, line, arg) ||
454 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
455 warnif_rule_after_reqadd(proxy, file, line, arg) ||
456 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200457 warnif_rule_after_use_backend(proxy, file, line, arg) ||
458 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200459}
460
461/* report a warning if an http-request rule is dangerously placed */
462int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
463{
Willy Tarreau61d18892009-03-31 10:49:21 +0200464 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
465 warnif_rule_after_reqadd(proxy, file, line, arg) ||
466 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200467 warnif_rule_after_use_backend(proxy, file, line, arg) ||
468 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200469}
470
471/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100472int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200473{
474 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
475 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200476 warnif_rule_after_use_backend(proxy, file, line, arg) ||
477 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200478}
479
480/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100481int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200482{
483 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200484 warnif_rule_after_use_backend(proxy, file, line, arg) ||
485 warnif_rule_after_use_server(proxy, file, line, arg);
486}
487
488/* report a warning if a redirect rule is dangerously placed */
489int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
490{
491 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
492 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200493}
494
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100495/* Report it if a request ACL condition uses some keywords that are incompatible
496 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
497 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
498 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100499 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100500static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100501{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100502 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200503 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100504
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100505 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100506 return 0;
507
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100508 acl = acl_cond_conflicts(cond, where);
509 if (acl) {
510 if (acl->name && *acl->name)
511 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
512 file, line, acl->name, sample_ckp_names(where));
513 else
514 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 +0200515 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100516 return ERR_WARN;
517 }
518 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100519 return 0;
520
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100521 if (acl->name && *acl->name)
522 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200523 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100524 else
525 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200526 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100527 return ERR_WARN;
528}
529
Willy Tarreaubaaee002006-06-26 02:48:02 +0200530/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200531 * parse a line in a <global> section. Returns the error code, 0 if OK, or
532 * any combination of :
533 * - ERR_ABORT: must abort ASAP
534 * - ERR_FATAL: we can continue parsing but not start the service
535 * - ERR_WARN: a warning has been emitted
536 * - ERR_ALERT: an alert has been emitted
537 * Only the two first ones can stop processing, the two others are just
538 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200539 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200540int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200541{
Willy Tarreau058e9072009-07-20 09:30:05 +0200542 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200543 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200544
545 if (!strcmp(args[0], "global")) { /* new section */
546 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200549 else if (!strcmp(args[0], "ca-base")) {
550#ifdef USE_OPENSSL
551 if (global.ca_base != NULL) {
552 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
553 err_code |= ERR_ALERT;
554 goto out;
555 }
556 if (*(args[1]) == 0) {
557 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
558 err_code |= ERR_ALERT | ERR_FATAL;
559 goto out;
560 }
561 global.ca_base = strdup(args[1]);
562#else
563 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
564 err_code |= ERR_ALERT | ERR_FATAL;
565 goto out;
566#endif
567 }
568 else if (!strcmp(args[0], "crt-base")) {
569#ifdef USE_OPENSSL
570 if (global.crt_base != NULL) {
571 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
572 err_code |= ERR_ALERT;
573 goto out;
574 }
575 if (*(args[1]) == 0) {
576 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
577 err_code |= ERR_ALERT | ERR_FATAL;
578 goto out;
579 }
580 global.crt_base = strdup(args[1]);
581#else
582 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
583 err_code |= ERR_ALERT | ERR_FATAL;
584 goto out;
585#endif
586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587 else if (!strcmp(args[0], "daemon")) {
588 global.mode |= MODE_DAEMON;
589 }
590 else if (!strcmp(args[0], "debug")) {
591 global.mode |= MODE_DEBUG;
592 }
593 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100594 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200596 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100597 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200598 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100600 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100602 else if (!strcmp(args[0], "nosplice")) {
603 global.tune.options &= ~GTUNE_USE_SPLICE;
604 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200605 else if (!strcmp(args[0], "nogetaddrinfo")) {
606 global.tune.options &= ~GTUNE_USE_GAI;
607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 else if (!strcmp(args[0], "quiet")) {
609 global.mode |= MODE_QUIET;
610 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200611 else if (!strcmp(args[0], "tune.maxpollevents")) {
612 if (global.tune.maxpollevents != 0) {
613 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200614 err_code |= ERR_ALERT;
615 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200616 }
617 if (*(args[1]) == 0) {
618 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200619 err_code |= ERR_ALERT | ERR_FATAL;
620 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200621 }
622 global.tune.maxpollevents = atol(args[1]);
623 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100624 else if (!strcmp(args[0], "tune.maxaccept")) {
625 if (global.tune.maxaccept != 0) {
626 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200627 err_code |= ERR_ALERT;
628 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100629 }
630 if (*(args[1]) == 0) {
631 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT | ERR_FATAL;
633 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100634 }
635 global.tune.maxaccept = atol(args[1]);
636 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200637 else if (!strcmp(args[0], "tune.chksize")) {
638 if (*(args[1]) == 0) {
639 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
640 err_code |= ERR_ALERT | ERR_FATAL;
641 goto out;
642 }
643 global.tune.chksize = atol(args[1]);
644 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200645#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200646 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
647 global.tune.sslprivatecache = 1;
648 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100649 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200650 if (*(args[1]) == 0) {
651 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT | ERR_FATAL;
653 goto out;
654 }
655 global.tune.sslcachesize = atol(args[1]);
656 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100657 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
658 unsigned int ssllifetime;
659 const char *res;
660
661 if (*(args[1]) == 0) {
662 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
665 }
666
667 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
668 if (res) {
669 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
670 file, linenum, *res, args[0]);
671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
673 }
674
675 global.tune.ssllifetime = ssllifetime;
676 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100677 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
682 }
683 global.tune.ssl_max_record = atol(args[1]);
684 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200685 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
690 }
691 global.tune.ssl_default_dh_param = atol(args[1]);
692 if (global.tune.ssl_default_dh_param < 1024) {
693 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200698#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200699 else if (!strcmp(args[0], "tune.bufsize")) {
700 if (*(args[1]) == 0) {
701 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704 }
705 global.tune.bufsize = atol(args[1]);
706 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
707 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100708 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100709 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200710 }
711 else if (!strcmp(args[0], "tune.maxrewrite")) {
712 if (*(args[1]) == 0) {
713 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
714 err_code |= ERR_ALERT | ERR_FATAL;
715 goto out;
716 }
717 global.tune.maxrewrite = atol(args[1]);
718 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
719 global.tune.maxrewrite = global.tune.bufsize / 2;
720 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100721 else if (!strcmp(args[0], "tune.idletimer")) {
722 unsigned int idle;
723 const char *res;
724
725 if (*(args[1]) == 0) {
726 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
727 err_code |= ERR_ALERT | ERR_FATAL;
728 goto out;
729 }
730
731 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
732 if (res) {
733 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
734 file, linenum, *res, args[0]);
735 err_code |= ERR_ALERT | ERR_FATAL;
736 goto out;
737 }
738
739 if (idle > 65535) {
740 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
743 }
744 global.tune.idle_timer = idle;
745 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100746 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
747 if (global.tune.client_rcvbuf != 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.client_rcvbuf = atol(args[1]);
758 }
759 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
760 if (global.tune.server_rcvbuf != 0) {
761 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
762 err_code |= ERR_ALERT;
763 goto out;
764 }
765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
769 }
770 global.tune.server_rcvbuf = atol(args[1]);
771 }
772 else if (!strcmp(args[0], "tune.sndbuf.client")) {
773 if (global.tune.client_sndbuf != 0) {
774 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
775 err_code |= ERR_ALERT;
776 goto out;
777 }
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
783 global.tune.client_sndbuf = atol(args[1]);
784 }
785 else if (!strcmp(args[0], "tune.sndbuf.server")) {
786 if (global.tune.server_sndbuf != 0) {
787 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
788 err_code |= ERR_ALERT;
789 goto out;
790 }
791 if (*(args[1]) == 0) {
792 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
793 err_code |= ERR_ALERT | ERR_FATAL;
794 goto out;
795 }
796 global.tune.server_sndbuf = atol(args[1]);
797 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200798 else if (!strcmp(args[0], "tune.pipesize")) {
799 if (*(args[1]) == 0) {
800 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
801 err_code |= ERR_ALERT | ERR_FATAL;
802 goto out;
803 }
804 global.tune.pipesize = atol(args[1]);
805 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100806 else if (!strcmp(args[0], "tune.http.cookielen")) {
807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
811 }
812 global.tune.cookie_len = atol(args[1]) + 1;
813 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200814 else if (!strcmp(args[0], "tune.http.maxhdr")) {
815 if (*(args[1]) == 0) {
816 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
817 err_code |= ERR_ALERT | ERR_FATAL;
818 goto out;
819 }
820 global.tune.max_http_hdr = atol(args[1]);
821 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100822 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
823#ifdef USE_ZLIB
824 if (*args[1]) {
825 global.tune.zlibmemlevel = atoi(args[1]);
826 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
827 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
828 file, linenum, args[0]);
829 err_code |= ERR_ALERT | ERR_FATAL;
830 goto out;
831 }
832 } else {
833 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
834 file, linenum, args[0]);
835 err_code |= ERR_ALERT | ERR_FATAL;
836 goto out;
837 }
838#else
839 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
842#endif
843 }
844 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
845#ifdef USE_ZLIB
846 if (*args[1]) {
847 global.tune.zlibwindowsize = atoi(args[1]);
848 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
849 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
850 file, linenum, args[0]);
851 err_code |= ERR_ALERT | ERR_FATAL;
852 goto out;
853 }
854 } else {
855 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
856 file, linenum, args[0]);
857 err_code |= ERR_ALERT | ERR_FATAL;
858 goto out;
859 }
860#else
861 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864#endif
865 }
William Lallemandf3747832012-11-09 12:33:10 +0100866 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
867 if (*args[1]) {
868 global.tune.comp_maxlevel = atoi(args[1]);
869 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
870 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
871 file, linenum, args[0]);
872 err_code |= ERR_ALERT | ERR_FATAL;
873 goto out;
874 }
875 } else {
876 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
877 file, linenum, args[0]);
878 err_code |= ERR_ALERT | ERR_FATAL;
879 goto out;
880 }
881 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882 else if (!strcmp(args[0], "uid")) {
883 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200884 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200885 err_code |= ERR_ALERT;
886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200887 }
888 if (*(args[1]) == 0) {
889 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 }
893 global.uid = atol(args[1]);
894 }
895 else if (!strcmp(args[0], "gid")) {
896 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200897 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200898 err_code |= ERR_ALERT;
899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 }
901 if (*(args[1]) == 0) {
902 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200903 err_code |= ERR_ALERT | ERR_FATAL;
904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200905 }
906 global.gid = atol(args[1]);
907 }
Simon Horman98637e52014-06-20 12:30:16 +0900908 else if (!strcmp(args[0], "external-check")) {
909 global.external_check = 1;
910 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200911 /* user/group name handling */
912 else if (!strcmp(args[0], "user")) {
913 struct passwd *ha_user;
914 if (global.uid != 0) {
915 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200916 err_code |= ERR_ALERT;
917 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200918 }
919 errno = 0;
920 ha_user = getpwnam(args[1]);
921 if (ha_user != NULL) {
922 global.uid = (int)ha_user->pw_uid;
923 }
924 else {
925 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 +0200926 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200927 }
928 }
929 else if (!strcmp(args[0], "group")) {
930 struct group *ha_group;
931 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200932 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200933 err_code |= ERR_ALERT;
934 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200935 }
936 errno = 0;
937 ha_group = getgrnam(args[1]);
938 if (ha_group != NULL) {
939 global.gid = (int)ha_group->gr_gid;
940 }
941 else {
942 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 +0200943 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200944 }
945 }
946 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 if (*(args[1]) == 0) {
949 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200950 err_code |= ERR_ALERT | ERR_FATAL;
951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952 }
953 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100954 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
955 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
956 file, linenum, args[0], LONGBITS, global.nbproc);
957 err_code |= ERR_ALERT | ERR_FATAL;
958 goto out;
959 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200960 }
961 else if (!strcmp(args[0], "maxconn")) {
962 if (global.maxconn != 0) {
963 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200964 err_code |= ERR_ALERT;
965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200966 }
967 if (*(args[1]) == 0) {
968 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200969 err_code |= ERR_ALERT | ERR_FATAL;
970 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200971 }
972 global.maxconn = atol(args[1]);
973#ifdef SYSTEM_MAXCONN
974 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
975 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);
976 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200977 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200978 }
979#endif /* SYSTEM_MAXCONN */
980 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200981 else if (!strcmp(args[0], "maxsslconn")) {
982#ifdef USE_OPENSSL
983 if (*(args[1]) == 0) {
984 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
985 err_code |= ERR_ALERT | ERR_FATAL;
986 goto out;
987 }
988 global.maxsslconn = atol(args[1]);
989#else
Emeric Brun0914df82012-10-02 18:45:42 +0200990 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200993#endif
994 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100995 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
996#ifdef USE_OPENSSL
997 if (*(args[1]) == 0) {
998 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
999 err_code |= ERR_ALERT | ERR_FATAL;
1000 goto out;
1001 }
1002 free(global.listen_default_ciphers);
1003 global.listen_default_ciphers = strdup(args[1]);
1004#else
1005 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1006 err_code |= ERR_ALERT | ERR_FATAL;
1007 goto out;
1008#endif
1009 }
1010 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1011#ifdef USE_OPENSSL
1012 if (*(args[1]) == 0) {
1013 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1014 err_code |= ERR_ALERT | ERR_FATAL;
1015 goto out;
1016 }
1017 free(global.connect_default_ciphers);
1018 global.connect_default_ciphers = strdup(args[1]);
1019#else
1020 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1021 err_code |= ERR_ALERT | ERR_FATAL;
1022 goto out;
1023#endif
1024 }
Emeric Brun850efd52014-01-29 12:24:34 +01001025 else if (!strcmp(args[0], "ssl-server-verify")) {
1026 if (*(args[1]) == 0) {
1027 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1028 err_code |= ERR_ALERT | ERR_FATAL;
1029 goto out;
1030 }
1031 if (strcmp(args[1],"none") == 0)
1032 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1033 else if (strcmp(args[1],"required") == 0)
1034 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1035 else {
1036 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1037 err_code |= ERR_ALERT | ERR_FATAL;
1038 goto out;
1039 }
1040 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001041 else if (!strcmp(args[0], "maxconnrate")) {
1042 if (global.cps_lim != 0) {
1043 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1044 err_code |= ERR_ALERT;
1045 goto out;
1046 }
1047 if (*(args[1]) == 0) {
1048 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1049 err_code |= ERR_ALERT | ERR_FATAL;
1050 goto out;
1051 }
1052 global.cps_lim = atol(args[1]);
1053 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001054 else if (!strcmp(args[0], "maxsessrate")) {
1055 if (global.sps_lim != 0) {
1056 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1057 err_code |= ERR_ALERT;
1058 goto out;
1059 }
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 }
1065 global.sps_lim = atol(args[1]);
1066 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001067 else if (!strcmp(args[0], "maxsslrate")) {
1068 if (global.ssl_lim != 0) {
1069 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1070 err_code |= ERR_ALERT;
1071 goto out;
1072 }
1073 if (*(args[1]) == 0) {
1074 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1075 err_code |= ERR_ALERT | ERR_FATAL;
1076 goto out;
1077 }
1078 global.ssl_lim = atol(args[1]);
1079 }
William Lallemandd85f9172012-11-09 17:05:39 +01001080 else if (!strcmp(args[0], "maxcomprate")) {
1081 if (*(args[1]) == 0) {
1082 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1083 err_code |= ERR_ALERT | ERR_FATAL;
1084 goto out;
1085 }
1086 global.comp_rate_lim = atoi(args[1]) * 1024;
1087 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001088 else if (!strcmp(args[0], "maxpipes")) {
1089 if (global.maxpipes != 0) {
1090 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001091 err_code |= ERR_ALERT;
1092 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001093 }
1094 if (*(args[1]) == 0) {
1095 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001096 err_code |= ERR_ALERT | ERR_FATAL;
1097 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001098 }
1099 global.maxpipes = atol(args[1]);
1100 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001101 else if (!strcmp(args[0], "maxzlibmem")) {
1102 if (*(args[1]) == 0) {
1103 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1104 err_code |= ERR_ALERT | ERR_FATAL;
1105 goto out;
1106 }
William Lallemande3a7d992012-11-20 11:25:20 +01001107 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001108 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001109 else if (!strcmp(args[0], "maxcompcpuusage")) {
1110 if (*(args[1]) == 0) {
1111 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1112 err_code |= ERR_ALERT | ERR_FATAL;
1113 goto out;
1114 }
1115 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001116 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001117 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1118 err_code |= ERR_ALERT | ERR_FATAL;
1119 goto out;
1120 }
1121}
1122
Willy Tarreaubaaee002006-06-26 02:48:02 +02001123 else if (!strcmp(args[0], "ulimit-n")) {
1124 if (global.rlimit_nofile != 0) {
1125 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT;
1127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 }
1129 if (*(args[1]) == 0) {
1130 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001131 err_code |= ERR_ALERT | ERR_FATAL;
1132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001133 }
1134 global.rlimit_nofile = atol(args[1]);
1135 }
1136 else if (!strcmp(args[0], "chroot")) {
1137 if (global.chroot != NULL) {
1138 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001139 err_code |= ERR_ALERT;
1140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 }
1142 if (*(args[1]) == 0) {
1143 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001144 err_code |= ERR_ALERT | ERR_FATAL;
1145 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001146 }
1147 global.chroot = strdup(args[1]);
1148 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001149 else if (!strcmp(args[0], "description")) {
1150 int i, len=0;
1151 char *d;
1152
1153 if (!*args[1]) {
1154 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1155 file, linenum, args[0]);
1156 err_code |= ERR_ALERT | ERR_FATAL;
1157 goto out;
1158 }
1159
Willy Tarreau348acfe2014-04-14 15:00:39 +02001160 for (i = 1; *args[i]; i++)
1161 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001162
1163 if (global.desc)
1164 free(global.desc);
1165
1166 global.desc = d = (char *)calloc(1, len);
1167
Willy Tarreau348acfe2014-04-14 15:00:39 +02001168 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1169 for (i = 2; *args[i]; i++)
1170 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001171 }
1172 else if (!strcmp(args[0], "node")) {
1173 int i;
1174 char c;
1175
1176 for (i=0; args[1][i]; i++) {
1177 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001178 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1179 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001180 break;
1181 }
1182
1183 if (!i || args[1][i]) {
1184 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1185 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1186 file, linenum, args[0]);
1187 err_code |= ERR_ALERT | ERR_FATAL;
1188 goto out;
1189 }
1190
1191 if (global.node)
1192 free(global.node);
1193
1194 global.node = strdup(args[1]);
1195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001196 else if (!strcmp(args[0], "pidfile")) {
1197 if (global.pidfile != NULL) {
1198 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001199 err_code |= ERR_ALERT;
1200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001201 }
1202 if (*(args[1]) == 0) {
1203 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001204 err_code |= ERR_ALERT | ERR_FATAL;
1205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001206 }
1207 global.pidfile = strdup(args[1]);
1208 }
Emeric Bruned760922010-10-22 17:59:25 +02001209 else if (!strcmp(args[0], "unix-bind")) {
1210 int cur_arg = 1;
1211 while (*(args[cur_arg])) {
1212 if (!strcmp(args[cur_arg], "prefix")) {
1213 if (global.unix_bind.prefix != NULL) {
1214 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1215 err_code |= ERR_ALERT;
1216 cur_arg += 2;
1217 continue;
1218 }
1219
1220 if (*(args[cur_arg+1]) == 0) {
1221 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto out;
1224 }
1225 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1226 cur_arg += 2;
1227 continue;
1228 }
1229
1230 if (!strcmp(args[cur_arg], "mode")) {
1231
1232 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1233 cur_arg += 2;
1234 continue;
1235 }
1236
1237 if (!strcmp(args[cur_arg], "uid")) {
1238
1239 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1240 cur_arg += 2;
1241 continue;
1242 }
1243
1244 if (!strcmp(args[cur_arg], "gid")) {
1245
1246 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1247 cur_arg += 2;
1248 continue;
1249 }
1250
1251 if (!strcmp(args[cur_arg], "user")) {
1252 struct passwd *user;
1253
1254 user = getpwnam(args[cur_arg + 1]);
1255 if (!user) {
1256 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1257 file, linenum, args[0], args[cur_arg + 1 ]);
1258 err_code |= ERR_ALERT | ERR_FATAL;
1259 goto out;
1260 }
1261
1262 global.unix_bind.ux.uid = user->pw_uid;
1263 cur_arg += 2;
1264 continue;
1265 }
1266
1267 if (!strcmp(args[cur_arg], "group")) {
1268 struct group *group;
1269
1270 group = getgrnam(args[cur_arg + 1]);
1271 if (!group) {
1272 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1273 file, linenum, args[0], args[cur_arg + 1 ]);
1274 err_code |= ERR_ALERT | ERR_FATAL;
1275 goto out;
1276 }
1277
1278 global.unix_bind.ux.gid = group->gr_gid;
1279 cur_arg += 2;
1280 continue;
1281 }
1282
Willy Tarreaub48f9582011-09-05 01:17:06 +02001283 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001284 file, linenum, args[0]);
1285 err_code |= ERR_ALERT | ERR_FATAL;
1286 goto out;
1287 }
1288 }
William Lallemand0f99e342011-10-12 17:50:54 +02001289 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1290 /* delete previous herited or defined syslog servers */
1291 struct logsrv *back;
1292 struct logsrv *tmp;
1293
1294 if (*(args[1]) != 0) {
1295 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1296 err_code |= ERR_ALERT | ERR_FATAL;
1297 goto out;
1298 }
1299
1300 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1301 LIST_DEL(&tmp->list);
1302 free(tmp);
1303 }
1304 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001305 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001306 struct sockaddr_storage *sk;
1307 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001308 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001309 int arg = 0;
1310 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001311
Willy Tarreaubaaee002006-06-26 02:48:02 +02001312 if (*(args[1]) == 0 || *(args[2]) == 0) {
1313 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001314 err_code |= ERR_ALERT | ERR_FATAL;
1315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001316 }
William Lallemand0f99e342011-10-12 17:50:54 +02001317
1318 logsrv = calloc(1, sizeof(struct logsrv));
1319
Willy Tarreau18324f52014-06-27 18:10:07 +02001320 /* just after the address, a length may be specified */
1321 if (strcmp(args[arg+2], "len") == 0) {
1322 len = atoi(args[arg+3]);
1323 if (len < 80 || len > 65535) {
1324 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1325 file, linenum, args[arg+3]);
1326 err_code |= ERR_ALERT | ERR_FATAL;
1327 goto out;
1328 }
1329 logsrv->maxlen = len;
1330
1331 /* skip these two args */
1332 arg += 2;
1333 }
1334 else
1335 logsrv->maxlen = MAX_SYSLOG_LEN;
1336
1337 if (logsrv->maxlen > global.max_syslog_len) {
1338 global.max_syslog_len = logsrv->maxlen;
1339 logline = realloc(logline, global.max_syslog_len + 1);
1340 }
1341
1342 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001343 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001344 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001345 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001346 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001347 }
1348
William Lallemand0f99e342011-10-12 17:50:54 +02001349 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001350 if (*(args[arg+3])) {
1351 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001352 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001353 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001354 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001355 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001356 }
1357 }
1358
William Lallemand0f99e342011-10-12 17:50:54 +02001359 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001360 if (*(args[arg+4])) {
1361 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001362 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001363 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001364 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001365 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001366 }
1367 }
1368
Willy Tarreau902636f2013-03-10 19:44:48 +01001369 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001370 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001371 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001372 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001373 free(logsrv);
1374 goto out;
1375 }
1376 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001377
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001378 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001379 if (port1 != port2) {
1380 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1381 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001382 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001383 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001384 goto out;
1385 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001386
William Lallemand0f99e342011-10-12 17:50:54 +02001387 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001388 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001389 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001390 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391
William Lallemand0f99e342011-10-12 17:50:54 +02001392 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001393 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001394 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1395 char *name;
1396 int len;
1397
1398 if (global.log_send_hostname != NULL) {
1399 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1400 err_code |= ERR_ALERT;
1401 goto out;
1402 }
1403
1404 if (*(args[1]))
1405 name = args[1];
1406 else
1407 name = hostname;
1408
1409 len = strlen(name);
1410
1411 /* We'll add a space after the name to respect the log format */
1412 free(global.log_send_hostname);
1413 global.log_send_hostname = malloc(len + 2);
1414 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1415 }
Kevinm48936af2010-12-22 16:08:21 +00001416 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1417 if (*(args[1]) == 0) {
1418 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1419 err_code |= ERR_ALERT | ERR_FATAL;
1420 goto out;
1421 }
1422 free(global.log_tag);
1423 global.log_tag = strdup(args[1]);
1424 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001425 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1426 if (global.spread_checks != 0) {
1427 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001428 err_code |= ERR_ALERT;
1429 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001430 }
1431 if (*(args[1]) == 0) {
1432 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001433 err_code |= ERR_ALERT | ERR_FATAL;
1434 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001435 }
1436 global.spread_checks = atol(args[1]);
1437 if (global.spread_checks < 0 || global.spread_checks > 50) {
1438 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001439 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001440 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001441 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001442 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1443 const char *err;
1444 unsigned int val;
1445
1446
1447 if (*(args[1]) == 0) {
1448 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1449 err_code |= ERR_ALERT | ERR_FATAL;
1450 goto out;
1451 }
1452
1453 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1454 if (err) {
1455 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1456 err_code |= ERR_ALERT | ERR_FATAL;
1457 }
1458 global.max_spread_checks = val;
1459 if (global.max_spread_checks < 0) {
1460 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1461 err_code |= ERR_ALERT | ERR_FATAL;
1462 }
1463 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001464 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1465#ifdef USE_CPU_AFFINITY
1466 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001467 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001468 unsigned long cpus = 0;
1469
1470 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001471 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001472 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001473 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001474 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001475 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001476 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001477 proc = atol(args[1]);
1478 if (proc >= 1 && proc <= LONGBITS)
1479 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001480 }
1481
1482 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001483 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",
1484 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001485 err_code |= ERR_ALERT | ERR_FATAL;
1486 goto out;
1487 }
1488
1489 cur_arg = 2;
1490 while (*args[cur_arg]) {
1491 unsigned int low, high;
1492
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001493 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001494 char *dash = strchr(args[cur_arg], '-');
1495
1496 low = high = str2uic(args[cur_arg]);
1497 if (dash)
1498 high = str2uic(dash + 1);
1499
1500 if (high < low) {
1501 unsigned int swap = low;
1502 low = high;
1503 high = swap;
1504 }
1505
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001506 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001507 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001508 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001509 err_code |= ERR_ALERT | ERR_FATAL;
1510 goto out;
1511 }
1512
1513 while (low <= high)
1514 cpus |= 1UL << low++;
1515 }
1516 else {
1517 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1518 file, linenum, args[0], args[cur_arg]);
1519 err_code |= ERR_ALERT | ERR_FATAL;
1520 goto out;
1521 }
1522 cur_arg++;
1523 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001524 for (i = 0; i < LONGBITS; i++)
1525 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001526 global.cpu_map[i] = cpus;
1527#else
1528 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1529 err_code |= ERR_ALERT | ERR_FATAL;
1530 goto out;
1531#endif
1532 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001533 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001534 struct cfg_kw_list *kwl;
1535 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001536 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001537
1538 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1539 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1540 if (kwl->kw[index].section != CFG_GLOBAL)
1541 continue;
1542 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001543 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001544 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001545 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001546 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001547 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001548 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001549 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001550 err_code |= ERR_WARN;
1551 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001552 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001553 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001554 }
1555 }
1556 }
1557
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001559 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001561
Willy Tarreau058e9072009-07-20 09:30:05 +02001562 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001563 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001564 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565}
1566
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001567void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001569 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 defproxy.mode = PR_MODE_TCP;
1571 defproxy.state = PR_STNEW;
1572 defproxy.maxconn = cfg_maxpconn;
1573 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001574
Simon Horman66183002013-02-23 10:16:43 +09001575 defproxy.defsrv.check.inter = DEF_CHKINTR;
1576 defproxy.defsrv.check.fastinter = 0;
1577 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001578 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1579 defproxy.defsrv.agent.fastinter = 0;
1580 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001581 defproxy.defsrv.check.rise = DEF_RISETIME;
1582 defproxy.defsrv.check.fall = DEF_FALLTIME;
1583 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1584 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001585 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001586 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001587 defproxy.defsrv.maxqueue = 0;
1588 defproxy.defsrv.minconn = 0;
1589 defproxy.defsrv.maxconn = 0;
1590 defproxy.defsrv.slowstart = 0;
1591 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1592 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1593 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001594}
1595
Willy Tarreauade5ec42010-01-28 19:33:49 +01001596
Willy Tarreau63af98d2014-05-18 08:11:41 +02001597/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1598 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1599 * ERR_FATAL in case of error.
1600 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001601static int create_cond_regex_rule(const char *file, int line,
1602 struct proxy *px, int dir, int action, int flags,
1603 const char *cmd, const char *reg, const char *repl,
1604 const char **cond_start)
1605{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001606 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001607 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001608 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001609 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001610 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001611 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001612 int cs;
1613 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001614
1615 if (px == &defproxy) {
1616 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001617 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001618 goto err;
1619 }
1620
1621 if (*reg == 0) {
1622 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
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
1627 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001628 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001629
Willy Tarreau5321c422010-01-28 20:35:13 +01001630 if (cond_start &&
1631 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001632 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1633 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1634 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001635 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001636 goto err;
1637 }
1638 }
1639 else if (cond_start && **cond_start) {
1640 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1641 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001642 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001643 goto err;
1644 }
1645
Willy Tarreau63af98d2014-05-18 08:11:41 +02001646 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001647 (dir == SMP_OPT_DIR_REQ) ?
1648 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1649 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1650 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001651
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001652 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001653 if (!preg) {
1654 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001655 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001656 goto err;
1657 }
1658
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001659 cs = !(flags & REG_ICASE);
1660 cap = !(flags & REG_NOSUB);
1661 error = NULL;
1662 if (!regex_comp(reg, preg, cs, cap, &error)) {
1663 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1664 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001665 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001666 goto err;
1667 }
1668
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001669 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001670 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001671 if (repl && err) {
1672 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1673 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001674 ret_code |= ERR_ALERT | ERR_FATAL;
1675 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001676 }
1677
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001678 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001679 ret_code |= ERR_WARN;
1680
1681 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001682
Willy Tarreau63af98d2014-05-18 08:11:41 +02001683 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001684 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001685 err:
1686 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001687 free(errmsg);
1688 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001689}
1690
Willy Tarreaubaaee002006-06-26 02:48:02 +02001691/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001692 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001693 * Returns the error code, 0 if OK, or any combination of :
1694 * - ERR_ABORT: must abort ASAP
1695 * - ERR_FATAL: we can continue parsing but not start the service
1696 * - ERR_WARN: a warning has been emitted
1697 * - ERR_ALERT: an alert has been emitted
1698 * Only the two first ones can stop processing, the two others are just
1699 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001700 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001701int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1702{
1703 static struct peers *curpeers = NULL;
1704 struct peer *newpeer = NULL;
1705 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001706 struct bind_conf *bind_conf;
1707 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001708 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001709 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001710
1711 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001712 if (!*args[1]) {
1713 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001714 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001715 goto out;
1716 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001717
1718 err = invalid_char(args[1]);
1719 if (err) {
1720 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1721 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001722 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001723 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001724 }
1725
1726 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1727 /*
1728 * If there are two proxies with the same name only following
1729 * combinations are allowed:
1730 */
1731 if (strcmp(curpeers->id, args[1]) == 0) {
1732 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1733 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1734 err_code |= ERR_WARN;
1735 }
1736 }
1737
1738 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1739 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1740 err_code |= ERR_ALERT | ERR_ABORT;
1741 goto out;
1742 }
1743
1744 curpeers->next = peers;
1745 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001746 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001747 curpeers->conf.line = linenum;
1748 curpeers->last_change = now.tv_sec;
1749 curpeers->id = strdup(args[1]);
1750 }
1751 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001752 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001753 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001754 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001755
1756 if (!*args[2]) {
1757 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1758 file, linenum, args[0]);
1759 err_code |= ERR_ALERT | ERR_FATAL;
1760 goto out;
1761 }
1762
1763 err = invalid_char(args[1]);
1764 if (err) {
1765 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1766 file, linenum, *err, args[1]);
1767 err_code |= ERR_ALERT | ERR_FATAL;
1768 goto out;
1769 }
1770
1771 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1772 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1773 err_code |= ERR_ALERT | ERR_ABORT;
1774 goto out;
1775 }
1776
1777 /* the peers are linked backwards first */
1778 curpeers->count++;
1779 newpeer->next = curpeers->remote;
1780 curpeers->remote = newpeer;
1781 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001782 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001783 newpeer->conf.line = linenum;
1784
1785 newpeer->last_change = now.tv_sec;
1786 newpeer->id = strdup(args[1]);
1787
Willy Tarreau902636f2013-03-10 19:44:48 +01001788 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001789 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001790 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001791 err_code |= ERR_ALERT | ERR_FATAL;
1792 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001793 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001794
1795 proto = protocol_by_family(sk->ss_family);
1796 if (!proto || !proto->connect) {
1797 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1798 file, linenum, args[0], args[1]);
1799 err_code |= ERR_ALERT | ERR_FATAL;
1800 goto out;
1801 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001802
1803 if (port1 != port2) {
1804 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1805 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001806 err_code |= ERR_ALERT | ERR_FATAL;
1807 goto out;
1808 }
1809
Willy Tarreau2aa38802013-02-20 19:20:59 +01001810 if (!port1) {
1811 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1812 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001813 err_code |= ERR_ALERT | ERR_FATAL;
1814 goto out;
1815 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001816
Emeric Brun32da3c42010-09-23 18:39:19 +02001817 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001818 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001819 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001820 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001821
Emeric Brun32da3c42010-09-23 18:39:19 +02001822 if (strcmp(newpeer->id, localpeer) == 0) {
1823 /* Current is local peer, it define a frontend */
1824 newpeer->local = 1;
1825
1826 if (!curpeers->peers_fe) {
1827 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1828 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1829 err_code |= ERR_ALERT | ERR_ABORT;
1830 goto out;
1831 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001832
Willy Tarreau237250c2011-07-29 01:49:03 +02001833 init_new_proxy(curpeers->peers_fe);
1834 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001835
1836 curpeers->peers_fe->last_change = now.tv_sec;
1837 curpeers->peers_fe->id = strdup(args[1]);
1838 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001839 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001840 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1841 curpeers->peers_fe->timeout.connect = 5000;
1842 curpeers->peers_fe->accept = peer_accept;
1843 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001844 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1845 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001846
1847 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1848
Willy Tarreau902636f2013-03-10 19:44:48 +01001849 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1850 if (errmsg && *errmsg) {
1851 indent_msg(&errmsg, 2);
1852 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001853 }
1854 else
1855 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1856 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001857 err_code |= ERR_FATAL;
1858 goto out;
1859 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001860
1861 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001862 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001863 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1864 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1865 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1866 l->accept = session_accept;
1867 l->handler = process_session;
1868 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1869 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1870 global.maxsock += l->maxconn;
1871 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001872 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001873 else {
1874 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1875 file, linenum, args[0], args[1],
1876 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1877 err_code |= ERR_FATAL;
1878 goto out;
1879 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001880 }
1881 } /* neither "peer" nor "peers" */
1882 else if (*args[0] != 0) {
1883 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1884 err_code |= ERR_ALERT | ERR_FATAL;
1885 goto out;
1886 }
1887
1888out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001889 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001890 return err_code;
1891}
1892
Willy Tarreau3842f002009-06-14 11:39:52 +02001893int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894{
1895 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001896 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001897 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001898 int rc;
1899 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001900 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001901 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001902 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001903 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001904 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001905
Willy Tarreau977b8e42006-12-29 14:19:17 +01001906 if (!strcmp(args[0], "listen"))
1907 rc = PR_CAP_LISTEN;
1908 else if (!strcmp(args[0], "frontend"))
1909 rc = PR_CAP_FE | PR_CAP_RS;
1910 else if (!strcmp(args[0], "backend"))
1911 rc = PR_CAP_BE | PR_CAP_RS;
1912 else if (!strcmp(args[0], "ruleset"))
1913 rc = PR_CAP_RS;
1914 else
1915 rc = PR_CAP_NONE;
1916
1917 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001918 struct ebpt_node *node;
1919
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920 if (!*args[1]) {
1921 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1922 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1923 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001924 err_code |= ERR_ALERT | ERR_ABORT;
1925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001926 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001927
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001928 err = invalid_char(args[1]);
1929 if (err) {
1930 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1931 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001932 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001933 }
1934
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001935 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1936 curproxy = container_of(node, struct proxy, conf.by_name);
1937
1938 if (strcmp(curproxy->id, args[1]) != 0)
1939 break;
1940
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001941 /*
1942 * If there are two proxies with the same name only following
1943 * combinations are allowed:
1944 *
1945 * listen backend frontend ruleset
1946 * listen - - - -
1947 * backend - - OK -
1948 * frontend - OK - -
1949 * ruleset - - - -
1950 */
1951
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001952 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1953 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001954 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1955 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1956 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001957 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001958 }
1959 }
1960
Willy Tarreaubaaee002006-06-26 02:48:02 +02001961 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1962 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001963 err_code |= ERR_ALERT | ERR_ABORT;
1964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001965 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001966
Willy Tarreau97cb7802010-01-03 20:23:58 +01001967 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001968 curproxy->next = proxy;
1969 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001970 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1971 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001972 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001974 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001975 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976
1977 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001978 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001979 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001980
Willy Tarreau4348fad2012-09-20 16:48:07 +02001981 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1982
Willy Tarreau902636f2013-03-10 19:44:48 +01001983 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1984 if (errmsg && *errmsg) {
1985 indent_msg(&errmsg, 2);
1986 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001987 }
1988 else
1989 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1990 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001991 err_code |= ERR_FATAL;
1992 goto out;
1993 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001994
Willy Tarreau4348fad2012-09-20 16:48:07 +02001995 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001996 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001997 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001998 }
1999
2000 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002001 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002002 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002003
Willy Tarreaubaaee002006-06-26 02:48:02 +02002004 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002005 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002006 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002007 curproxy->no_options = defproxy.no_options;
2008 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002009 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002010 curproxy->except_net = defproxy.except_net;
2011 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002012 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002013 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002014
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002015 if (defproxy.fwdfor_hdr_len) {
2016 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2017 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2018 }
2019
Willy Tarreaub86db342009-11-30 11:50:16 +01002020 if (defproxy.orgto_hdr_len) {
2021 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2022 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2023 }
2024
Mark Lamourinec2247f02012-01-04 13:02:01 -05002025 if (defproxy.server_id_hdr_len) {
2026 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2027 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2028 }
2029
Willy Tarreau977b8e42006-12-29 14:19:17 +01002030 if (curproxy->cap & PR_CAP_FE) {
2031 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002032 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002033 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002034
2035 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002036 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2037 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002038
2039 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2040 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041
Willy Tarreau977b8e42006-12-29 14:19:17 +01002042 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002043 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002044 curproxy->fullconn = defproxy.fullconn;
2045 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002046 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002047
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002048 if (defproxy.check_req) {
2049 curproxy->check_req = calloc(1, defproxy.check_len);
2050 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2051 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002052 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002053
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002054 if (defproxy.expect_str) {
2055 curproxy->expect_str = strdup(defproxy.expect_str);
2056 if (defproxy.expect_regex) {
2057 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002058 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2059 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002060 }
2061 }
2062
Willy Tarreau67402132012-05-31 20:40:20 +02002063 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002064 if (defproxy.cookie_name)
2065 curproxy->cookie_name = strdup(defproxy.cookie_name);
2066 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002067 if (defproxy.cookie_domain)
2068 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002069
Willy Tarreau31936852010-10-06 16:59:56 +02002070 if (defproxy.cookie_maxidle)
2071 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2072
2073 if (defproxy.cookie_maxlife)
2074 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2075
Emeric Brun647caf12009-06-30 17:57:00 +02002076 if (defproxy.rdp_cookie_name)
2077 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2078 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2079
Willy Tarreau01732802007-11-01 22:48:15 +01002080 if (defproxy.url_param_name)
2081 curproxy->url_param_name = strdup(defproxy.url_param_name);
2082 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002083
Benoitaffb4812009-03-25 13:02:10 +01002084 if (defproxy.hh_name)
2085 curproxy->hh_name = strdup(defproxy.hh_name);
2086 curproxy->hh_len = defproxy.hh_len;
2087 curproxy->hh_match_domain = defproxy.hh_match_domain;
2088
Willy Tarreauef9a3602012-12-08 22:29:20 +01002089 if (defproxy.conn_src.iface_name)
2090 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2091 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002092 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002093#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002094 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002095#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002096 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002098 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002099 if (defproxy.capture_name)
2100 curproxy->capture_name = strdup(defproxy.capture_name);
2101 curproxy->capture_namelen = defproxy.capture_namelen;
2102 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002103 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104
Willy Tarreau977b8e42006-12-29 14:19:17 +01002105 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002106 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002107 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002108 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002109 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002110 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002111 curproxy->mon_net = defproxy.mon_net;
2112 curproxy->mon_mask = defproxy.mon_mask;
2113 if (defproxy.monitor_uri)
2114 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2115 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002116 if (defproxy.defbe.name)
2117 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002118
2119 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002120 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2121 if (curproxy->conf.logformat_string &&
2122 curproxy->conf.logformat_string != default_http_log_format &&
2123 curproxy->conf.logformat_string != default_tcp_log_format &&
2124 curproxy->conf.logformat_string != clf_http_log_format)
2125 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2126
2127 if (defproxy.conf.lfs_file) {
2128 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2129 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2130 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002131 }
2132
2133 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002134 curproxy->timeout.connect = defproxy.timeout.connect;
2135 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002136 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002137 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002138 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002139 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002140 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002141 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002142 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002143 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002144 }
2145
Willy Tarreaubaaee002006-06-26 02:48:02 +02002146 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002147 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002148
2149 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002150 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002151 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002152 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002153 LIST_INIT(&node->list);
2154 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2155 }
2156
Willy Tarreau62a61232013-04-12 18:13:46 +02002157 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2158 if (curproxy->conf.uniqueid_format_string)
2159 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2160
2161 if (defproxy.conf.uif_file) {
2162 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2163 curproxy->conf.uif_line = defproxy.conf.uif_line;
2164 }
William Lallemanda73203e2012-03-12 12:48:57 +01002165
2166 /* copy default header unique id */
2167 if (defproxy.header_unique_id)
2168 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2169
William Lallemand82fe75c2012-10-23 10:25:10 +02002170 /* default compression options */
2171 if (defproxy.comp != NULL) {
2172 curproxy->comp = calloc(1, sizeof(struct comp));
2173 curproxy->comp->algos = defproxy.comp->algos;
2174 curproxy->comp->types = defproxy.comp->types;
2175 }
2176
Willy Tarreaubaaee002006-06-26 02:48:02 +02002177 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002178 curproxy->conf.used_listener_id = EB_ROOT;
2179 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002180
Simon Horman98637e52014-06-20 12:30:16 +09002181 if (defproxy.check_path)
2182 curproxy->check_path = strdup(defproxy.check_path);
2183 if (defproxy.check_command)
2184 curproxy->check_command = strdup(defproxy.check_command);
2185
Willy Tarreau93893792009-07-23 13:19:11 +02002186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002187 }
2188 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2189 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002190 /* FIXME-20070101: we should do this too at the end of the
2191 * config parsing to free all default values.
2192 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002193 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002194 free(defproxy.check_command);
2195 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002196 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002197 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002198 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002199 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002200 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002201 free(defproxy.capture_name);
2202 free(defproxy.monitor_uri);
2203 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002204 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002205 free(defproxy.fwdfor_hdr_name);
2206 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002207 free(defproxy.orgto_hdr_name);
2208 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002209 free(defproxy.server_id_hdr_name);
2210 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002211 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002212 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002213 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002214 free(defproxy.expect_regex);
2215 defproxy.expect_regex = NULL;
2216 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002217
Willy Tarreau62a61232013-04-12 18:13:46 +02002218 if (defproxy.conf.logformat_string != default_http_log_format &&
2219 defproxy.conf.logformat_string != default_tcp_log_format &&
2220 defproxy.conf.logformat_string != clf_http_log_format)
2221 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002222
Willy Tarreau62a61232013-04-12 18:13:46 +02002223 free(defproxy.conf.uniqueid_format_string);
2224 free(defproxy.conf.lfs_file);
2225 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002226
Willy Tarreaua534fea2008-08-03 12:19:50 +02002227 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002228 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002229
Willy Tarreaubaaee002006-06-26 02:48:02 +02002230 /* we cannot free uri_auth because it might already be used */
2231 init_default_instance();
2232 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002233 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2234 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002235 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002237 }
2238 else if (curproxy == NULL) {
2239 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002240 err_code |= ERR_ALERT | ERR_FATAL;
2241 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002243
2244 /* update the current file and line being parsed */
2245 curproxy->conf.args.file = curproxy->conf.file;
2246 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002247
2248 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002249 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2250 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2251 if (err_code & ERR_FATAL)
2252 goto out;
2253 }
2254 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002255 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002256 int cur_arg;
2257
Willy Tarreaubaaee002006-06-26 02:48:02 +02002258 if (curproxy == &defproxy) {
2259 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002260 err_code |= ERR_ALERT | ERR_FATAL;
2261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002262 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002263 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002264 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265
Willy Tarreau24709282013-03-10 21:32:12 +01002266 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002267 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002268 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002271 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002272
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002273 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002274
2275 /* use default settings for unix sockets */
2276 bind_conf->ux.uid = global.unix_bind.ux.uid;
2277 bind_conf->ux.gid = global.unix_bind.ux.gid;
2278 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002279
2280 /* NOTE: the following line might create several listeners if there
2281 * are comma-separated IPs or port ranges. So all further processing
2282 * will have to be applied to all listeners created after last_listen.
2283 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002284 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2285 if (errmsg && *errmsg) {
2286 indent_msg(&errmsg, 2);
2287 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002288 }
2289 else
2290 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2291 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002292 err_code |= ERR_ALERT | ERR_FATAL;
2293 goto out;
2294 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002295
Willy Tarreau4348fad2012-09-20 16:48:07 +02002296 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2297 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002298 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002299 }
2300
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002301 cur_arg = 2;
2302 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002303 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002304 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002305 char *err;
2306
Willy Tarreau26982662012-09-12 23:17:10 +02002307 kw = bind_find_kw(args[cur_arg]);
2308 if (kw) {
2309 char *err = NULL;
2310 int code;
2311
2312 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002313 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2314 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002315 cur_arg += 1 + kw->skip ;
2316 err_code |= ERR_ALERT | ERR_FATAL;
2317 goto out;
2318 }
2319
Willy Tarreau4348fad2012-09-20 16:48:07 +02002320 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002321 err_code |= code;
2322
2323 if (code) {
2324 if (err && *err) {
2325 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002326 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002327 }
2328 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002329 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2330 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002331 if (code & ERR_FATAL) {
2332 free(err);
2333 cur_arg += 1 + kw->skip;
2334 goto out;
2335 }
2336 }
2337 free(err);
2338 cur_arg += 1 + kw->skip;
2339 continue;
2340 }
2341
Willy Tarreau8638f482012-09-18 18:01:17 +02002342 err = NULL;
2343 if (!bind_dumped) {
2344 bind_dump_kws(&err);
2345 indent_msg(&err, 4);
2346 bind_dumped = 1;
2347 }
2348
2349 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2350 file, linenum, args[0], args[1], args[cur_arg],
2351 err ? " Registered keywords :" : "", err ? err : "");
2352 free(err);
2353
Willy Tarreau93893792009-07-23 13:19:11 +02002354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002356 }
Willy Tarreau93893792009-07-23 13:19:11 +02002357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002358 }
2359 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002360 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2362 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002363 err_code |= ERR_ALERT | ERR_FATAL;
2364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002365 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002366 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002367 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002368
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 /* flush useless bits */
2370 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002373 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002374 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002375 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002376
Willy Tarreau1c47f852006-07-09 08:22:27 +02002377 if (!*args[1]) {
2378 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2379 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002380 err_code |= ERR_ALERT | ERR_FATAL;
2381 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002382 }
2383
Willy Tarreaua534fea2008-08-03 12:19:50 +02002384 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002385 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002386 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002387 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002388 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2389
Willy Tarreau93893792009-07-23 13:19:11 +02002390 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2393 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2394 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2395 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2396 else {
2397 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002398 err_code |= ERR_ALERT | ERR_FATAL;
2399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 }
2401 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002402 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002403 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002404
2405 if (curproxy == &defproxy) {
2406 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2407 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002408 err_code |= ERR_ALERT | ERR_FATAL;
2409 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002410 }
2411
2412 if (!*args[1]) {
2413 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2414 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002417 }
2418
2419 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002420 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002421
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002422 if (curproxy->uuid <= 0) {
2423 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002424 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002425 err_code |= ERR_ALERT | ERR_FATAL;
2426 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002427 }
2428
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002429 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2430 if (node) {
2431 struct proxy *target = container_of(node, struct proxy, conf.id);
2432 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2433 file, linenum, proxy_type_str(curproxy), curproxy->id,
2434 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
2437 }
2438 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002439 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002440 else if (!strcmp(args[0], "description")) {
2441 int i, len=0;
2442 char *d;
2443
Cyril Bonté99ed3272010-01-24 23:29:44 +01002444 if (curproxy == &defproxy) {
2445 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2446 file, linenum, args[0]);
2447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
2449 }
2450
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002451 if (!*args[1]) {
2452 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2453 file, linenum, args[0]);
2454 return -1;
2455 }
2456
Willy Tarreau348acfe2014-04-14 15:00:39 +02002457 for (i = 1; *args[i]; i++)
2458 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002459
2460 d = (char *)calloc(1, len);
2461 curproxy->desc = d;
2462
Willy Tarreau348acfe2014-04-14 15:00:39 +02002463 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2464 for (i = 2; *args[i]; i++)
2465 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002466
2467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002468 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2469 curproxy->state = PR_STSTOPPED;
2470 }
2471 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2472 curproxy->state = PR_STNEW;
2473 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002474 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2475 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002476 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002477
2478 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002479 unsigned int low, high;
2480
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002481 if (strcmp(args[cur_arg], "all") == 0) {
2482 set = 0;
2483 break;
2484 }
2485 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002486 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002487 }
2488 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002489 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002490 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002491 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002492 char *dash = strchr(args[cur_arg], '-');
2493
2494 low = high = str2uic(args[cur_arg]);
2495 if (dash)
2496 high = str2uic(dash + 1);
2497
2498 if (high < low) {
2499 unsigned int swap = low;
2500 low = high;
2501 high = swap;
2502 }
2503
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002504 if (low < 1 || high > LONGBITS) {
2505 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2506 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002507 err_code |= ERR_ALERT | ERR_FATAL;
2508 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002509 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002510 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002511 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002512 }
2513 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002514 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2515 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002516 err_code |= ERR_ALERT | ERR_FATAL;
2517 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002518 }
2519 cur_arg++;
2520 }
2521 curproxy->bind_proc = set;
2522 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002523 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002524 if (curproxy == &defproxy) {
2525 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002526 err_code |= ERR_ALERT | ERR_FATAL;
2527 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002528 }
2529
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002530 err = invalid_char(args[1]);
2531 if (err) {
2532 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2533 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002534 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002535 }
2536
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002537 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002538 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2539 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002542 }
2543 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002544 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2545 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002546
Willy Tarreau977b8e42006-12-29 14:19:17 +01002547 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002548 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002549
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 if (*(args[1]) == 0) {
2551 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2552 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002553 err_code |= ERR_ALERT | ERR_FATAL;
2554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002555 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002556
Willy Tarreau67402132012-05-31 20:40:20 +02002557 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002558 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002559 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002560 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 curproxy->cookie_name = strdup(args[1]);
2562 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002563
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 cur_arg = 2;
2565 while (*(args[cur_arg])) {
2566 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002567 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568 }
2569 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002570 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 }
2572 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002573 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 }
2575 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002576 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 }
2578 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002579 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002581 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002582 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002584 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002585 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002587 else if (!strcmp(args[cur_arg], "httponly")) {
2588 curproxy->ck_opts |= PR_CK_HTTPONLY;
2589 }
2590 else if (!strcmp(args[cur_arg], "secure")) {
2591 curproxy->ck_opts |= PR_CK_SECURE;
2592 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002593 else if (!strcmp(args[cur_arg], "domain")) {
2594 if (!*args[cur_arg + 1]) {
2595 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2596 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002597 err_code |= ERR_ALERT | ERR_FATAL;
2598 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002599 }
2600
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002601 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002602 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002603 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2604 " dots nor does not start with a dot."
2605 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002606 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002607 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002608 }
2609
2610 err = invalid_domainchar(args[cur_arg + 1]);
2611 if (err) {
2612 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2613 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002616 }
2617
Willy Tarreau68a897b2009-12-03 23:28:34 +01002618 if (!curproxy->cookie_domain) {
2619 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2620 } else {
2621 /* one domain was already specified, add another one by
2622 * building the string which will be returned along with
2623 * the cookie.
2624 */
2625 char *new_ptr;
2626 int new_len = strlen(curproxy->cookie_domain) +
2627 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2628 new_ptr = malloc(new_len);
2629 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2630 free(curproxy->cookie_domain);
2631 curproxy->cookie_domain = new_ptr;
2632 }
Willy Tarreau31936852010-10-06 16:59:56 +02002633 cur_arg++;
2634 }
2635 else if (!strcmp(args[cur_arg], "maxidle")) {
2636 unsigned int maxidle;
2637 const char *res;
2638
2639 if (!*args[cur_arg + 1]) {
2640 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2641 file, linenum, args[cur_arg]);
2642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
2644 }
2645
2646 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2647 if (res) {
2648 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2649 file, linenum, *res, args[cur_arg]);
2650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
2652 }
2653 curproxy->cookie_maxidle = maxidle;
2654 cur_arg++;
2655 }
2656 else if (!strcmp(args[cur_arg], "maxlife")) {
2657 unsigned int maxlife;
2658 const char *res;
2659
2660 if (!*args[cur_arg + 1]) {
2661 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2662 file, linenum, args[cur_arg]);
2663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
2665 }
2666
2667 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2668 if (res) {
2669 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2670 file, linenum, *res, args[cur_arg]);
2671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
2673 }
2674 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002675 cur_arg++;
2676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002677 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002678 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 +02002679 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002680 err_code |= ERR_ALERT | ERR_FATAL;
2681 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002682 }
2683 cur_arg++;
2684 }
Willy Tarreau67402132012-05-31 20:40:20 +02002685 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002686 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2687 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002688 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002689 }
2690
Willy Tarreau67402132012-05-31 20:40:20 +02002691 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2693 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002695 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002696
Willy Tarreau67402132012-05-31 20:40:20 +02002697 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002698 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2699 file, linenum);
2700 err_code |= ERR_ALERT | ERR_FATAL;
2701 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002702 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman98637e52014-06-20 12:30:16 +09002703 else if (!strcmp(args[0], "external-check")) {
2704 if (*(args[1]) == 0) {
2705 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2706 file, linenum, args[0]);
2707 err_code |= ERR_ALERT | ERR_FATAL;
2708 goto out;
2709 }
2710
2711 if (!strcmp(args[1], "command")) {
2712 if (*(args[1]) == 0) {
2713 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2714 file, linenum, args[1]);
2715 err_code |= ERR_ALERT | ERR_FATAL;
2716 goto out;
2717 }
2718 free(curproxy->check_command);
2719 curproxy->check_command = strdup(args[2]);
2720 }
2721 else if (!strcmp(args[1], "path")) {
2722 if (*(args[1]) == 0) {
2723 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2724 file, linenum, args[1]);
2725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
2727 }
2728 free(curproxy->check_path);
2729 curproxy->check_path = strdup(args[2]);
2730 }
2731 else {
2732 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
2733 file, linenum, args[1]);
2734 err_code |= ERR_ALERT | ERR_FATAL;
2735 goto out;
2736 }
2737 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002738 else if (!strcmp(args[0], "persist")) { /* persist */
2739 if (*(args[1]) == 0) {
2740 Alert("parsing [%s:%d] : missing persist method.\n",
2741 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002742 err_code |= ERR_ALERT | ERR_FATAL;
2743 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002744 }
2745
2746 if (!strncmp(args[1], "rdp-cookie", 10)) {
2747 curproxy->options2 |= PR_O2_RDPC_PRST;
2748
Emeric Brunb982a3d2010-01-04 15:45:53 +01002749 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002750 const char *beg, *end;
2751
2752 beg = args[1] + 11;
2753 end = strchr(beg, ')');
2754
2755 if (!end || end == beg) {
2756 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2757 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002760 }
2761
2762 free(curproxy->rdp_cookie_name);
2763 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2764 curproxy->rdp_cookie_len = end-beg;
2765 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002766 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002767 free(curproxy->rdp_cookie_name);
2768 curproxy->rdp_cookie_name = strdup("msts");
2769 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2770 }
2771 else { /* syntax */
2772 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2773 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002774 err_code |= ERR_ALERT | ERR_FATAL;
2775 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002776 }
2777 }
2778 else {
2779 Alert("parsing [%s:%d] : unknown persist method.\n",
2780 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002781 err_code |= ERR_ALERT | ERR_FATAL;
2782 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002783 }
2784 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002785 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002786 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002787
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002788 if (curproxy == &defproxy) {
2789 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
2792 }
2793
Willy Tarreau977b8e42006-12-29 14:19:17 +01002794 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002795 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002796
Willy Tarreaubaaee002006-06-26 02:48:02 +02002797 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002798 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002799 file, linenum, args[0]);
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 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002804 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002805 curproxy->appsession_name = strdup(args[1]);
2806 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2807 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002808 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2809 if (err) {
2810 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2811 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002812 err_code |= ERR_ALERT | ERR_FATAL;
2813 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002814 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002815 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002816
Willy Tarreau51041c72007-09-09 21:56:53 +02002817 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2818 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002819 err_code |= ERR_ALERT | ERR_ABORT;
2820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002821 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002822
2823 cur_arg = 6;
2824 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002825 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2826 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002827 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002828 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002829 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002830 } else if (!strcmp(args[cur_arg], "prefix")) {
2831 curproxy->options2 |= PR_O2_AS_PFX;
2832 } else if (!strcmp(args[cur_arg], "mode")) {
2833 if (!*args[cur_arg + 1]) {
2834 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2835 file, linenum, args[0], args[cur_arg]);
2836 err_code |= ERR_ALERT | ERR_FATAL;
2837 goto out;
2838 }
2839
2840 cur_arg++;
2841 if (!strcmp(args[cur_arg], "query-string")) {
2842 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2843 curproxy->options2 |= PR_O2_AS_M_QS;
2844 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2845 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2846 curproxy->options2 |= PR_O2_AS_M_PP;
2847 } else {
2848 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
2851 }
2852 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002853 cur_arg++;
2854 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855 } /* Url App Session */
2856 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002857 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002858 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002859
Willy Tarreaubaaee002006-06-26 02:48:02 +02002860 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002861 if (curproxy == &defproxy) {
2862 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2863 err_code |= ERR_ALERT | ERR_FATAL;
2864 goto out;
2865 }
2866
Willy Tarreaubaaee002006-06-26 02:48:02 +02002867 if (*(args[4]) == 0) {
2868 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2869 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002870 err_code |= ERR_ALERT | ERR_FATAL;
2871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002873 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002874 curproxy->capture_name = strdup(args[2]);
2875 curproxy->capture_namelen = strlen(curproxy->capture_name);
2876 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002877 curproxy->to_log |= LW_COOKIE;
2878 }
2879 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2880 struct cap_hdr *hdr;
2881
2882 if (curproxy == &defproxy) {
2883 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 +02002884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002886 }
2887
2888 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2889 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2890 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002891 err_code |= ERR_ALERT | ERR_FATAL;
2892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002893 }
2894
2895 hdr = calloc(sizeof(struct cap_hdr), 1);
2896 hdr->next = curproxy->req_cap;
2897 hdr->name = strdup(args[3]);
2898 hdr->namelen = strlen(args[3]);
2899 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002900 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002901 hdr->index = curproxy->nb_req_cap++;
2902 curproxy->req_cap = hdr;
2903 curproxy->to_log |= LW_REQHDR;
2904 }
2905 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2906 struct cap_hdr *hdr;
2907
2908 if (curproxy == &defproxy) {
2909 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 +02002910 err_code |= ERR_ALERT | ERR_FATAL;
2911 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912 }
2913
2914 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2915 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2916 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002917 err_code |= ERR_ALERT | ERR_FATAL;
2918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002919 }
2920 hdr = calloc(sizeof(struct cap_hdr), 1);
2921 hdr->next = curproxy->rsp_cap;
2922 hdr->name = strdup(args[3]);
2923 hdr->namelen = strlen(args[3]);
2924 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002925 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002926 hdr->index = curproxy->nb_rsp_cap++;
2927 curproxy->rsp_cap = hdr;
2928 curproxy->to_log |= LW_RSPHDR;
2929 }
2930 else {
2931 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2932 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002933 err_code |= ERR_ALERT | ERR_FATAL;
2934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002935 }
2936 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002937 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002938 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002939 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002940
Willy Tarreaubaaee002006-06-26 02:48:02 +02002941 if (*(args[1]) == 0) {
2942 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2943 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002944 err_code |= ERR_ALERT | ERR_FATAL;
2945 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002946 }
2947 curproxy->conn_retries = atol(args[1]);
2948 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002949 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002950 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002951
2952 if (curproxy == &defproxy) {
2953 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2954 err_code |= ERR_ALERT | ERR_FATAL;
2955 goto out;
2956 }
2957
Willy Tarreau20b0de52012-12-24 15:45:22 +01002958 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2959 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2960 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2961 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002962 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002963 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2964 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 +01002965 file, linenum, args[0]);
2966 err_code |= ERR_WARN;
2967 }
2968
Willy Tarreauff011f22011-01-06 17:51:27 +01002969 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002970
Willy Tarreauff011f22011-01-06 17:51:27 +01002971 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002972 err_code |= ERR_ALERT | ERR_ABORT;
2973 goto out;
2974 }
2975
Willy Tarreau5002f572014-04-23 01:32:02 +02002976 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002977 err_code |= warnif_cond_conflicts(rule->cond,
2978 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2979 file, linenum);
2980
Willy Tarreauff011f22011-01-06 17:51:27 +01002981 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002982 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002983 else if (!strcmp(args[0], "http-response")) { /* response access control */
2984 struct http_res_rule *rule;
2985
2986 if (curproxy == &defproxy) {
2987 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
2990 }
2991
2992 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2993 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2994 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2995 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2996 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2997 file, linenum, args[0]);
2998 err_code |= ERR_WARN;
2999 }
3000
3001 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3002
3003 if (!rule) {
3004 err_code |= ERR_ALERT | ERR_ABORT;
3005 goto out;
3006 }
3007
3008 err_code |= warnif_cond_conflicts(rule->cond,
3009 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3010 file, linenum);
3011
3012 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3013 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003014 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3015 /* set the header name and length into the proxy structure */
3016 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3017 err_code |= ERR_WARN;
3018
3019 if (!*args[1]) {
3020 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3021 file, linenum, args[0]);
3022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
3024 }
3025
3026 /* set the desired header name */
3027 free(curproxy->server_id_hdr_name);
3028 curproxy->server_id_hdr_name = strdup(args[1]);
3029 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3030 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003031 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003032 struct http_req_rule *rule;
3033
Willy Tarreaub099aca2008-10-12 17:26:37 +02003034 if (curproxy == &defproxy) {
3035 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003038 }
3039
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003040 /* emulate "block" using "http-request block". Since these rules are supposed to
3041 * be processed before all http-request rules, we put them into their own list
3042 * and will insert them at the end.
3043 */
3044 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3045 if (!rule) {
3046 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003047 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003048 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003049 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3050 err_code |= warnif_cond_conflicts(rule->cond,
3051 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3052 file, linenum);
3053 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003054
3055 if (!already_warned(WARN_BLOCK_DEPRECATED))
3056 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]);
3057
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003058 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003059 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003060 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003061
Cyril Bonté99ed3272010-01-24 23:29:44 +01003062 if (curproxy == &defproxy) {
3063 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
3066 }
3067
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003068 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003069 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3070 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003073 }
3074
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003075 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003076 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003077 err_code |= warnif_cond_conflicts(rule->cond,
3078 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3079 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003080 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003081 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003082 struct switching_rule *rule;
3083
Willy Tarreaub099aca2008-10-12 17:26:37 +02003084 if (curproxy == &defproxy) {
3085 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003086 err_code |= ERR_ALERT | ERR_FATAL;
3087 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003088 }
3089
Willy Tarreau55ea7572007-06-17 19:56:27 +02003090 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003091 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003092
3093 if (*(args[1]) == 0) {
3094 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003095 err_code |= ERR_ALERT | ERR_FATAL;
3096 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003097 }
3098
Willy Tarreauf51658d2014-04-23 01:21:56 +02003099 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3100 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3101 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3102 file, linenum, errmsg);
3103 err_code |= ERR_ALERT | ERR_FATAL;
3104 goto out;
3105 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003106
Willy Tarreauf51658d2014-04-23 01:21:56 +02003107 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003108 }
3109
3110 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3111 rule->cond = cond;
3112 rule->be.name = strdup(args[1]);
3113 LIST_INIT(&rule->list);
3114 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3115 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003116 else if (strcmp(args[0], "use-server") == 0) {
3117 struct server_rule *rule;
3118
3119 if (curproxy == &defproxy) {
3120 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3121 err_code |= ERR_ALERT | ERR_FATAL;
3122 goto out;
3123 }
3124
3125 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3126 err_code |= ERR_WARN;
3127
3128 if (*(args[1]) == 0) {
3129 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3130 err_code |= ERR_ALERT | ERR_FATAL;
3131 goto out;
3132 }
3133
3134 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3135 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3136 file, linenum, args[0]);
3137 err_code |= ERR_ALERT | ERR_FATAL;
3138 goto out;
3139 }
3140
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003141 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3142 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3143 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003144 err_code |= ERR_ALERT | ERR_FATAL;
3145 goto out;
3146 }
3147
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003148 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003149
3150 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3151 rule->cond = cond;
3152 rule->srv.name = strdup(args[1]);
3153 LIST_INIT(&rule->list);
3154 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3155 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3156 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003157 else if ((!strcmp(args[0], "force-persist")) ||
3158 (!strcmp(args[0], "ignore-persist"))) {
3159 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003160
3161 if (curproxy == &defproxy) {
3162 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
3165 }
3166
3167 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3168 err_code |= ERR_WARN;
3169
Willy Tarreauef6494c2010-01-28 17:12:36 +01003170 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003171 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3172 file, linenum, args[0]);
3173 err_code |= ERR_ALERT | ERR_FATAL;
3174 goto out;
3175 }
3176
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003177 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3178 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3179 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
3182 }
3183
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003184 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3185 * where force-persist is applied.
3186 */
3187 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003188
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003189 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003190 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003191 if (!strcmp(args[0], "force-persist")) {
3192 rule->type = PERSIST_TYPE_FORCE;
3193 } else {
3194 rule->type = PERSIST_TYPE_IGNORE;
3195 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003196 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003197 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003198 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003199 else if (!strcmp(args[0], "stick-table")) {
3200 int myidx = 1;
3201
Emeric Brun32da3c42010-09-23 18:39:19 +02003202 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003203 curproxy->table.type = (unsigned int)-1;
3204 while (*args[myidx]) {
3205 const char *err;
3206
3207 if (strcmp(args[myidx], "size") == 0) {
3208 myidx++;
3209 if (!*(args[myidx])) {
3210 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3211 file, linenum, args[myidx-1]);
3212 err_code |= ERR_ALERT | ERR_FATAL;
3213 goto out;
3214 }
3215 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3216 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3217 file, linenum, *err, args[myidx-1]);
3218 err_code |= ERR_ALERT | ERR_FATAL;
3219 goto out;
3220 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003221 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003222 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003223 else if (strcmp(args[myidx], "peers") == 0) {
3224 myidx++;
Godbach50523162013-12-11 19:48:57 +08003225 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003226 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3227 file, linenum, args[myidx-1]);
3228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
Godbach50523162013-12-11 19:48:57 +08003230 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003231 curproxy->table.peers.name = strdup(args[myidx++]);
3232 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003233 else if (strcmp(args[myidx], "expire") == 0) {
3234 myidx++;
3235 if (!*(args[myidx])) {
3236 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3237 file, linenum, args[myidx-1]);
3238 err_code |= ERR_ALERT | ERR_FATAL;
3239 goto out;
3240 }
3241 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3242 if (err) {
3243 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3244 file, linenum, *err, args[myidx-1]);
3245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
3247 }
3248 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003249 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003250 }
3251 else if (strcmp(args[myidx], "nopurge") == 0) {
3252 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003253 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003254 }
3255 else if (strcmp(args[myidx], "type") == 0) {
3256 myidx++;
3257 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3258 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3259 file, linenum, args[myidx]);
3260 err_code |= ERR_ALERT | ERR_FATAL;
3261 goto out;
3262 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003263 /* myidx already points to next arg */
3264 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003265 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003266 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003267 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003268
3269 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003270 nw = args[myidx];
3271 while (*nw) {
3272 /* the "store" keyword supports a comma-separated list */
3273 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003274 sa = NULL; /* store arg */
3275 while (*nw && *nw != ',') {
3276 if (*nw == '(') {
3277 *nw = 0;
3278 sa = ++nw;
3279 while (*nw != ')') {
3280 if (!*nw) {
3281 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3282 file, linenum, args[0], cw);
3283 err_code |= ERR_ALERT | ERR_FATAL;
3284 goto out;
3285 }
3286 nw++;
3287 }
3288 *nw = '\0';
3289 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003290 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003291 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003292 if (*nw)
3293 *nw++ = '\0';
3294 type = stktable_get_data_type(cw);
3295 if (type < 0) {
3296 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3297 file, linenum, args[0], cw);
3298 err_code |= ERR_ALERT | ERR_FATAL;
3299 goto out;
3300 }
Willy Tarreauac782882010-06-20 10:41:54 +02003301
3302 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3303 switch (err) {
3304 case PE_NONE: break;
3305 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003306 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3307 file, linenum, args[0], cw);
3308 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003309 break;
3310
3311 case PE_ARG_MISSING:
3312 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3313 file, linenum, args[0], cw);
3314 err_code |= ERR_ALERT | ERR_FATAL;
3315 goto out;
3316
3317 case PE_ARG_NOT_USED:
3318 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3319 file, linenum, args[0], cw);
3320 err_code |= ERR_ALERT | ERR_FATAL;
3321 goto out;
3322
3323 default:
3324 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3325 file, linenum, args[0], cw);
3326 err_code |= ERR_ALERT | ERR_FATAL;
3327 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003328 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003329 }
3330 myidx++;
3331 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003332 else {
3333 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3334 file, linenum, args[myidx]);
3335 err_code |= ERR_ALERT | ERR_FATAL;
3336 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003337 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003338 }
3339
3340 if (!curproxy->table.size) {
3341 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3342 file, linenum);
3343 err_code |= ERR_ALERT | ERR_FATAL;
3344 goto out;
3345 }
3346
3347 if (curproxy->table.type == (unsigned int)-1) {
3348 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3349 file, linenum);
3350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
3352 }
3353 }
3354 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003355 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003356 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003357 int myidx = 0;
3358 const char *name = NULL;
3359 int flags;
3360
3361 if (curproxy == &defproxy) {
3362 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3363 err_code |= ERR_ALERT | ERR_FATAL;
3364 goto out;
3365 }
3366
3367 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3368 err_code |= ERR_WARN;
3369 goto out;
3370 }
3371
3372 myidx++;
3373 if ((strcmp(args[myidx], "store") == 0) ||
3374 (strcmp(args[myidx], "store-request") == 0)) {
3375 myidx++;
3376 flags = STK_IS_STORE;
3377 }
3378 else if (strcmp(args[myidx], "store-response") == 0) {
3379 myidx++;
3380 flags = STK_IS_STORE | STK_ON_RSP;
3381 }
3382 else if (strcmp(args[myidx], "match") == 0) {
3383 myidx++;
3384 flags = STK_IS_MATCH;
3385 }
3386 else if (strcmp(args[myidx], "on") == 0) {
3387 myidx++;
3388 flags = STK_IS_MATCH | STK_IS_STORE;
3389 }
3390 else {
3391 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3392 err_code |= ERR_ALERT | ERR_FATAL;
3393 goto out;
3394 }
3395
3396 if (*(args[myidx]) == 0) {
3397 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3398 err_code |= ERR_ALERT | ERR_FATAL;
3399 goto out;
3400 }
3401
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003402 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003403 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003404 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003405 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
3408 }
3409
3410 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003411 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3412 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3413 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003414 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003415 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003416 goto out;
3417 }
3418 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003419 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3420 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3421 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003422 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003423 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003424 goto out;
3425 }
3426 }
3427
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003428 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003429 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003430
Emeric Brunb982a3d2010-01-04 15:45:53 +01003431 if (strcmp(args[myidx], "table") == 0) {
3432 myidx++;
3433 name = args[myidx++];
3434 }
3435
Willy Tarreauef6494c2010-01-28 17:12:36 +01003436 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003437 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3438 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3439 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003440 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003441 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003442 goto out;
3443 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003444 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003445 else if (*(args[myidx])) {
3446 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3447 file, linenum, args[0], args[myidx]);
3448 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003449 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003450 goto out;
3451 }
Emeric Brun97679e72010-09-23 17:56:44 +02003452 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003453 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003454 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003455 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003456
Emeric Brunb982a3d2010-01-04 15:45:53 +01003457 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3458 rule->cond = cond;
3459 rule->expr = expr;
3460 rule->flags = flags;
3461 rule->table.name = name ? strdup(name) : NULL;
3462 LIST_INIT(&rule->list);
3463 if (flags & STK_ON_RSP)
3464 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3465 else
3466 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003468 else if (!strcmp(args[0], "stats")) {
3469 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3470 curproxy->uri_auth = NULL; /* we must detach from the default config */
3471
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003472 if (!*args[1]) {
3473 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003474 } else if (!strcmp(args[1], "admin")) {
3475 struct stats_admin_rule *rule;
3476
3477 if (curproxy == &defproxy) {
3478 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3479 err_code |= ERR_ALERT | ERR_FATAL;
3480 goto out;
3481 }
3482
3483 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3484 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3485 err_code |= ERR_ALERT | ERR_ABORT;
3486 goto out;
3487 }
3488
3489 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3490 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3491 file, linenum, args[0], args[1]);
3492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
3494 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003495 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3496 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3497 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
3500 }
3501
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003502 err_code |= warnif_cond_conflicts(cond,
3503 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3504 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003505
3506 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3507 rule->cond = cond;
3508 LIST_INIT(&rule->list);
3509 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003510 } else if (!strcmp(args[1], "uri")) {
3511 if (*(args[2]) == 0) {
3512 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003513 err_code |= ERR_ALERT | ERR_FATAL;
3514 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003515 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
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 }
3520 } else if (!strcmp(args[1], "realm")) {
3521 if (*(args[2]) == 0) {
3522 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003523 err_code |= ERR_ALERT | ERR_FATAL;
3524 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003525 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3526 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003527 err_code |= ERR_ALERT | ERR_ABORT;
3528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003529 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003530 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003531 unsigned interval;
3532
3533 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3534 if (err) {
3535 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3536 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003537 err_code |= ERR_ALERT | ERR_FATAL;
3538 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003539 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3540 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003541 err_code |= ERR_ALERT | ERR_ABORT;
3542 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003543 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003544 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003545 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003546
3547 if (curproxy == &defproxy) {
3548 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3549 err_code |= ERR_ALERT | ERR_FATAL;
3550 goto out;
3551 }
3552
3553 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3554 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3555 err_code |= ERR_ALERT | ERR_ABORT;
3556 goto out;
3557 }
3558
Willy Tarreauff011f22011-01-06 17:51:27 +01003559 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3560 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003561 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3562 file, linenum, args[0]);
3563 err_code |= ERR_WARN;
3564 }
3565
Willy Tarreauff011f22011-01-06 17:51:27 +01003566 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003567
Willy Tarreauff011f22011-01-06 17:51:27 +01003568 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003569 err_code |= ERR_ALERT | ERR_ABORT;
3570 goto out;
3571 }
3572
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003573 err_code |= warnif_cond_conflicts(rule->cond,
3574 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3575 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003576 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003577
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 } else if (!strcmp(args[1], "auth")) {
3579 if (*(args[2]) == 0) {
3580 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003581 err_code |= ERR_ALERT | ERR_FATAL;
3582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003583 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3584 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003585 err_code |= ERR_ALERT | ERR_ABORT;
3586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003587 }
3588 } else if (!strcmp(args[1], "scope")) {
3589 if (*(args[2]) == 0) {
3590 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003591 err_code |= ERR_ALERT | ERR_FATAL;
3592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3594 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003595 err_code |= ERR_ALERT | ERR_ABORT;
3596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003597 }
3598 } else if (!strcmp(args[1], "enable")) {
3599 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3600 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003601 err_code |= ERR_ALERT | ERR_ABORT;
3602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003603 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003604 } else if (!strcmp(args[1], "hide-version")) {
3605 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3606 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003607 err_code |= ERR_ALERT | ERR_ABORT;
3608 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003609 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003610 } else if (!strcmp(args[1], "show-legends")) {
3611 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3612 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3613 err_code |= ERR_ALERT | ERR_ABORT;
3614 goto out;
3615 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003616 } else if (!strcmp(args[1], "show-node")) {
3617
3618 if (*args[2]) {
3619 int i;
3620 char c;
3621
3622 for (i=0; args[2][i]; i++) {
3623 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003624 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3625 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003626 break;
3627 }
3628
3629 if (!i || args[2][i]) {
3630 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3631 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3632 file, linenum, args[0], args[1]);
3633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
3635 }
3636 }
3637
3638 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3639 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3640 err_code |= ERR_ALERT | ERR_ABORT;
3641 goto out;
3642 }
3643 } else if (!strcmp(args[1], "show-desc")) {
3644 char *desc = NULL;
3645
3646 if (*args[2]) {
3647 int i, len=0;
3648 char *d;
3649
Willy Tarreau348acfe2014-04-14 15:00:39 +02003650 for (i = 2; *args[i]; i++)
3651 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003652
3653 desc = d = (char *)calloc(1, len);
3654
Willy Tarreau348acfe2014-04-14 15:00:39 +02003655 d += snprintf(d, desc + len - d, "%s", args[2]);
3656 for (i = 3; *args[i]; i++)
3657 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003658 }
3659
3660 if (!*args[2] && !global.desc)
3661 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3662 file, linenum, args[1]);
3663 else {
3664 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3665 free(desc);
3666 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3667 err_code |= ERR_ALERT | ERR_ABORT;
3668 goto out;
3669 }
3670 free(desc);
3671 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003672 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003673stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003674 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 +01003675 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003676 err_code |= ERR_ALERT | ERR_FATAL;
3677 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003678 }
3679 }
3680 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003681 int optnum;
3682
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003683 if (*(args[1]) == '\0') {
3684 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3685 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003686 err_code |= ERR_ALERT | ERR_FATAL;
3687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003688 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003689
3690 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3691 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003692 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3693 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3694 file, linenum, cfg_opts[optnum].name);
3695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
3697 }
Willy Tarreau93893792009-07-23 13:19:11 +02003698 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3699 err_code |= ERR_WARN;
3700 goto out;
3701 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003702
Willy Tarreau3842f002009-06-14 11:39:52 +02003703 curproxy->no_options &= ~cfg_opts[optnum].val;
3704 curproxy->options &= ~cfg_opts[optnum].val;
3705
3706 switch (kwm) {
3707 case KWM_STD:
3708 curproxy->options |= cfg_opts[optnum].val;
3709 break;
3710 case KWM_NO:
3711 curproxy->no_options |= cfg_opts[optnum].val;
3712 break;
3713 case KWM_DEF: /* already cleared */
3714 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003715 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003716
Willy Tarreau93893792009-07-23 13:19:11 +02003717 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003718 }
3719 }
3720
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003721 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3722 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003723 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3724 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3725 file, linenum, cfg_opts2[optnum].name);
3726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
3728 }
Willy Tarreau93893792009-07-23 13:19:11 +02003729 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3730 err_code |= ERR_WARN;
3731 goto out;
3732 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003733
Willy Tarreau3842f002009-06-14 11:39:52 +02003734 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3735 curproxy->options2 &= ~cfg_opts2[optnum].val;
3736
3737 switch (kwm) {
3738 case KWM_STD:
3739 curproxy->options2 |= cfg_opts2[optnum].val;
3740 break;
3741 case KWM_NO:
3742 curproxy->no_options2 |= cfg_opts2[optnum].val;
3743 break;
3744 case KWM_DEF: /* already cleared */
3745 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003746 }
Willy Tarreau93893792009-07-23 13:19:11 +02003747 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003748 }
3749 }
3750
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003751 /* HTTP options override each other. They can be cancelled using
3752 * "no option xxx" which only switches to default mode if the mode
3753 * was this one (useful for cancelling options set in defaults
3754 * sections).
3755 */
3756 if (strcmp(args[1], "httpclose") == 0) {
3757 if (kwm == KWM_STD) {
3758 curproxy->options &= ~PR_O_HTTP_MODE;
3759 curproxy->options |= PR_O_HTTP_PCL;
3760 goto out;
3761 }
3762 else if (kwm == KWM_NO) {
3763 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3764 curproxy->options &= ~PR_O_HTTP_MODE;
3765 goto out;
3766 }
3767 }
3768 else if (strcmp(args[1], "forceclose") == 0) {
3769 if (kwm == KWM_STD) {
3770 curproxy->options &= ~PR_O_HTTP_MODE;
3771 curproxy->options |= PR_O_HTTP_FCL;
3772 goto out;
3773 }
3774 else if (kwm == KWM_NO) {
3775 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3776 curproxy->options &= ~PR_O_HTTP_MODE;
3777 goto out;
3778 }
3779 }
3780 else if (strcmp(args[1], "http-server-close") == 0) {
3781 if (kwm == KWM_STD) {
3782 curproxy->options &= ~PR_O_HTTP_MODE;
3783 curproxy->options |= PR_O_HTTP_SCL;
3784 goto out;
3785 }
3786 else if (kwm == KWM_NO) {
3787 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3788 curproxy->options &= ~PR_O_HTTP_MODE;
3789 goto out;
3790 }
3791 }
3792 else if (strcmp(args[1], "http-keep-alive") == 0) {
3793 if (kwm == KWM_STD) {
3794 curproxy->options &= ~PR_O_HTTP_MODE;
3795 curproxy->options |= PR_O_HTTP_KAL;
3796 goto out;
3797 }
3798 else if (kwm == KWM_NO) {
3799 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3800 curproxy->options &= ~PR_O_HTTP_MODE;
3801 goto out;
3802 }
3803 }
3804 else if (strcmp(args[1], "http-tunnel") == 0) {
3805 if (kwm == KWM_STD) {
3806 curproxy->options &= ~PR_O_HTTP_MODE;
3807 curproxy->options |= PR_O_HTTP_TUN;
3808 goto out;
3809 }
3810 else if (kwm == KWM_NO) {
3811 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3812 curproxy->options &= ~PR_O_HTTP_MODE;
3813 goto out;
3814 }
3815 }
3816
Willy Tarreau3842f002009-06-14 11:39:52 +02003817 if (kwm != KWM_STD) {
3818 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003819 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003820 err_code |= ERR_ALERT | ERR_FATAL;
3821 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003822 }
3823
Emeric Brun3a058f32009-06-30 18:26:00 +02003824 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003825 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003826 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003827 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003828 if (*(args[2]) != '\0') {
3829 if (!strcmp(args[2], "clf")) {
3830 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003831 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003832 } else {
3833 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003836 }
3837 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003838 if (curproxy->conf.logformat_string != default_http_log_format &&
3839 curproxy->conf.logformat_string != default_tcp_log_format &&
3840 curproxy->conf.logformat_string != clf_http_log_format)
3841 free(curproxy->conf.logformat_string);
3842 curproxy->conf.logformat_string = logformat;
3843
3844 free(curproxy->conf.lfs_file);
3845 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3846 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003847 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003848 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003849 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003850 if (curproxy->conf.logformat_string != default_http_log_format &&
3851 curproxy->conf.logformat_string != default_tcp_log_format &&
3852 curproxy->conf.logformat_string != clf_http_log_format)
3853 free(curproxy->conf.logformat_string);
3854 curproxy->conf.logformat_string = default_tcp_log_format;
3855
3856 free(curproxy->conf.lfs_file);
3857 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3858 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003859 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003860 else if (!strcmp(args[1], "tcpka")) {
3861 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003862 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003863 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003864
3865 if (curproxy->cap & PR_CAP_FE)
3866 curproxy->options |= PR_O_TCP_CLI_KA;
3867 if (curproxy->cap & PR_CAP_BE)
3868 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003869 }
3870 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003871 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003872 err_code |= ERR_WARN;
3873
Willy Tarreaubaaee002006-06-26 02:48:02 +02003874 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003875 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003876 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003877 curproxy->options2 &= ~PR_O2_CHK_ANY;
3878 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003879 if (!*args[2]) { /* no argument */
3880 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3881 curproxy->check_len = strlen(DEF_CHECK_REQ);
3882 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003883 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003884 curproxy->check_req = (char *)malloc(reqlen);
3885 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003886 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003887 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003888 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003889 if (*args[4])
3890 reqlen += strlen(args[4]);
3891 else
3892 reqlen += strlen("HTTP/1.0");
3893
3894 curproxy->check_req = (char *)malloc(reqlen);
3895 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003896 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003897 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003898 }
3899 else if (!strcmp(args[1], "ssl-hello-chk")) {
3900 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003901 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003902 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003903
Willy Tarreaua534fea2008-08-03 12:19:50 +02003904 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003905 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003906 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003907 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003908 }
Willy Tarreau23677902007-05-08 23:50:35 +02003909 else if (!strcmp(args[1], "smtpchk")) {
3910 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003911 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003912 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003913 curproxy->options2 &= ~PR_O2_CHK_ANY;
3914 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003915
3916 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3917 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3918 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3919 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3920 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3921 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3922 curproxy->check_req = (char *)malloc(reqlen);
3923 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3924 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3925 } else {
3926 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3927 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3928 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3929 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3930 }
3931 }
3932 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003933 else if (!strcmp(args[1], "pgsql-check")) {
3934 /* use PostgreSQL request to check servers' health */
3935 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3936 err_code |= ERR_WARN;
3937
3938 free(curproxy->check_req);
3939 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003940 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003941 curproxy->options2 |= PR_O2_PGSQL_CHK;
3942
3943 if (*(args[2])) {
3944 int cur_arg = 2;
3945
3946 while (*(args[cur_arg])) {
3947 if (strcmp(args[cur_arg], "user") == 0) {
3948 char * packet;
3949 uint32_t packet_len;
3950 uint32_t pv;
3951
3952 /* suboption header - needs additional argument for it */
3953 if (*(args[cur_arg+1]) == 0) {
3954 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3955 file, linenum, args[0], args[1], args[cur_arg]);
3956 err_code |= ERR_ALERT | ERR_FATAL;
3957 goto out;
3958 }
3959
3960 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3961 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3962 pv = htonl(0x30000); /* protocol version 3.0 */
3963
3964 packet = (char*) calloc(1, packet_len);
3965
3966 memcpy(packet + 4, &pv, 4);
3967
3968 /* copy "user" */
3969 memcpy(packet + 8, "user", 4);
3970
3971 /* copy username */
3972 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3973
3974 free(curproxy->check_req);
3975 curproxy->check_req = packet;
3976 curproxy->check_len = packet_len;
3977
3978 packet_len = htonl(packet_len);
3979 memcpy(packet, &packet_len, 4);
3980 cur_arg += 2;
3981 } else {
3982 /* unknown suboption - catchall */
3983 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3984 file, linenum, args[0], args[1]);
3985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
3987 }
3988 } /* end while loop */
3989 }
3990 }
3991
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003992 else if (!strcmp(args[1], "redis-check")) {
3993 /* use REDIS PING request to check servers' health */
3994 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3995 err_code |= ERR_WARN;
3996
3997 free(curproxy->check_req);
3998 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003999 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004000 curproxy->options2 |= PR_O2_REDIS_CHK;
4001
4002 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4003 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4004 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4005 }
4006
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004007 else if (!strcmp(args[1], "mysql-check")) {
4008 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004009 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4010 err_code |= ERR_WARN;
4011
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004012 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004013 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004014 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004015 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004016
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004017 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004018 * const char mysql40_client_auth_pkt[] = {
4019 * "\x0e\x00\x00" // packet length
4020 * "\x01" // packet number
4021 * "\x00\x00" // client capabilities
4022 * "\x00\x00\x01" // max packet
4023 * "haproxy\x00" // username (null terminated string)
4024 * "\x00" // filler (always 0x00)
4025 * "\x01\x00\x00" // packet length
4026 * "\x00" // packet number
4027 * "\x01" // COM_QUIT command
4028 * };
4029 */
4030
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004031 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4032 * const char mysql41_client_auth_pkt[] = {
4033 * "\x0e\x00\x00\" // packet length
4034 * "\x01" // packet number
4035 * "\x00\x00\x00\x00" // client capabilities
4036 * "\x00\x00\x00\x01" // max packet
4037 * "\x21" // character set (UTF-8)
4038 * char[23] // All zeroes
4039 * "haproxy\x00" // username (null terminated string)
4040 * "\x00" // filler (always 0x00)
4041 * "\x01\x00\x00" // packet length
4042 * "\x00" // packet number
4043 * "\x01" // COM_QUIT command
4044 * };
4045 */
4046
4047
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004048 if (*(args[2])) {
4049 int cur_arg = 2;
4050
4051 while (*(args[cur_arg])) {
4052 if (strcmp(args[cur_arg], "user") == 0) {
4053 char *mysqluser;
4054 int packetlen, reqlen, userlen;
4055
4056 /* suboption header - needs additional argument for it */
4057 if (*(args[cur_arg+1]) == 0) {
4058 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4059 file, linenum, args[0], args[1], args[cur_arg]);
4060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
4062 }
4063 mysqluser = args[cur_arg + 1];
4064 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004065
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004066 if (*(args[cur_arg+2])) {
4067 if (!strcmp(args[cur_arg+2], "post-41")) {
4068 packetlen = userlen + 7 + 27;
4069 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004070
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004071 free(curproxy->check_req);
4072 curproxy->check_req = (char *)calloc(1, reqlen);
4073 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004074
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004075 snprintf(curproxy->check_req, 4, "%c%c%c",
4076 ((unsigned char) packetlen & 0xff),
4077 ((unsigned char) (packetlen >> 8) & 0xff),
4078 ((unsigned char) (packetlen >> 16) & 0xff));
4079
4080 curproxy->check_req[3] = 1;
4081 curproxy->check_req[5] = 130;
4082 curproxy->check_req[11] = 1;
4083 curproxy->check_req[12] = 33;
4084 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4085 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4086 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4087 cur_arg += 3;
4088 } else {
4089 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
4092 }
4093 } else {
4094 packetlen = userlen + 7;
4095 reqlen = packetlen + 9;
4096
4097 free(curproxy->check_req);
4098 curproxy->check_req = (char *)calloc(1, reqlen);
4099 curproxy->check_len = reqlen;
4100
4101 snprintf(curproxy->check_req, 4, "%c%c%c",
4102 ((unsigned char) packetlen & 0xff),
4103 ((unsigned char) (packetlen >> 8) & 0xff),
4104 ((unsigned char) (packetlen >> 16) & 0xff));
4105
4106 curproxy->check_req[3] = 1;
4107 curproxy->check_req[5] = 128;
4108 curproxy->check_req[8] = 1;
4109 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4110 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4111 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4112 cur_arg += 2;
4113 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004114 } else {
4115 /* unknown suboption - catchall */
4116 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4117 file, linenum, args[0], args[1]);
4118 err_code |= ERR_ALERT | ERR_FATAL;
4119 goto out;
4120 }
4121 } /* end while loop */
4122 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004123 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004124 else if (!strcmp(args[1], "ldap-check")) {
4125 /* use LDAP request to check servers' health */
4126 free(curproxy->check_req);
4127 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004128 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004129 curproxy->options2 |= PR_O2_LDAP_CHK;
4130
4131 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4132 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4133 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4134 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004135 else if (!strcmp(args[1], "tcp-check")) {
4136 /* use raw TCPCHK send/expect to check servers' health */
4137 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4138 err_code |= ERR_WARN;
4139
4140 free(curproxy->check_req);
4141 curproxy->check_req = NULL;
4142 curproxy->options2 &= ~PR_O2_CHK_ANY;
4143 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4144 }
Simon Horman98637e52014-06-20 12:30:16 +09004145 else if (!strcmp(args[1], "external-check")) {
4146 /* excute an external command to check servers' health */
4147 free(curproxy->check_req);
4148 curproxy->check_req = NULL;
4149 curproxy->options2 &= ~PR_O2_CHK_ANY;
4150 curproxy->options2 |= PR_O2_EXT_CHK;
4151 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004152 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004153 int cur_arg;
4154
4155 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4156 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004157 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004158
Willy Tarreau87cf5142011-08-19 22:57:24 +02004159 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004160
4161 free(curproxy->fwdfor_hdr_name);
4162 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4163 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4164
4165 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4166 cur_arg = 2;
4167 while (*(args[cur_arg])) {
4168 if (!strcmp(args[cur_arg], "except")) {
4169 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004170 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004171 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4172 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004173 err_code |= ERR_ALERT | ERR_FATAL;
4174 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004175 }
4176 /* flush useless bits */
4177 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004178 cur_arg += 2;
4179 } else if (!strcmp(args[cur_arg], "header")) {
4180 /* suboption header - needs additional argument for it */
4181 if (*(args[cur_arg+1]) == 0) {
4182 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4183 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004186 }
4187 free(curproxy->fwdfor_hdr_name);
4188 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4189 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4190 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004191 } else if (!strcmp(args[cur_arg], "if-none")) {
4192 curproxy->options &= ~PR_O_FF_ALWAYS;
4193 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004194 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004195 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004196 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004197 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004198 err_code |= ERR_ALERT | ERR_FATAL;
4199 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004200 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004201 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004202 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004203 else if (!strcmp(args[1], "originalto")) {
4204 int cur_arg;
4205
4206 /* insert x-original-to field, but not for the IP address listed as an except.
4207 * set default options (ie: bitfield, header name, etc)
4208 */
4209
4210 curproxy->options |= PR_O_ORGTO;
4211
4212 free(curproxy->orgto_hdr_name);
4213 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4214 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4215
Willy Tarreau87cf5142011-08-19 22:57:24 +02004216 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004217 cur_arg = 2;
4218 while (*(args[cur_arg])) {
4219 if (!strcmp(args[cur_arg], "except")) {
4220 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004221 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 +02004222 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4223 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004224 err_code |= ERR_ALERT | ERR_FATAL;
4225 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004226 }
4227 /* flush useless bits */
4228 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4229 cur_arg += 2;
4230 } else if (!strcmp(args[cur_arg], "header")) {
4231 /* suboption header - needs additional argument for it */
4232 if (*(args[cur_arg+1]) == 0) {
4233 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4234 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004235 err_code |= ERR_ALERT | ERR_FATAL;
4236 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004237 }
4238 free(curproxy->orgto_hdr_name);
4239 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4240 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4241 cur_arg += 2;
4242 } else {
4243 /* unknown suboption - catchall */
4244 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4245 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004246 err_code |= ERR_ALERT | ERR_FATAL;
4247 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004248 }
4249 } /* end while loop */
4250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004251 else {
4252 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004253 err_code |= ERR_ALERT | ERR_FATAL;
4254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004255 }
Willy Tarreau93893792009-07-23 13:19:11 +02004256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004257 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004258 else if (!strcmp(args[0], "default_backend")) {
4259 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004260 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004261
4262 if (*(args[1]) == 0) {
4263 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004264 err_code |= ERR_ALERT | ERR_FATAL;
4265 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004266 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004267 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004268 curproxy->defbe.name = strdup(args[1]);
4269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004270 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004271 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004272 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004273
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004274 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4275 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 +01004276 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004277 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004278 /* enable reconnections to dispatch */
4279 curproxy->options |= PR_O_REDISP;
4280 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004281 else if (!strcmp(args[0], "http-check")) {
4282 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004283 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004284
4285 if (strcmp(args[1], "disable-on-404") == 0) {
4286 /* enable a graceful server shutdown on an HTTP 404 response */
4287 curproxy->options |= PR_O_DISABLE404;
4288 }
Willy Tarreauef781042010-01-27 11:53:01 +01004289 else if (strcmp(args[1], "send-state") == 0) {
4290 /* enable emission of the apparent state of a server in HTTP checks */
4291 curproxy->options2 |= PR_O2_CHK_SNDST;
4292 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004293 else if (strcmp(args[1], "expect") == 0) {
4294 const char *ptr_arg;
4295 int cur_arg;
4296
4297 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4298 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
4301 }
4302
4303 cur_arg = 2;
4304 /* consider exclamation marks, sole or at the beginning of a word */
4305 while (*(ptr_arg = args[cur_arg])) {
4306 while (*ptr_arg == '!') {
4307 curproxy->options2 ^= PR_O2_EXP_INV;
4308 ptr_arg++;
4309 }
4310 if (*ptr_arg)
4311 break;
4312 cur_arg++;
4313 }
4314 /* now ptr_arg points to the beginning of a word past any possible
4315 * exclamation mark, and cur_arg is the argument which holds this word.
4316 */
4317 if (strcmp(ptr_arg, "status") == 0) {
4318 if (!*(args[cur_arg + 1])) {
4319 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4320 file, linenum, args[0], args[1], ptr_arg);
4321 err_code |= ERR_ALERT | ERR_FATAL;
4322 goto out;
4323 }
4324 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004325 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004326 curproxy->expect_str = strdup(args[cur_arg + 1]);
4327 }
4328 else if (strcmp(ptr_arg, "string") == 0) {
4329 if (!*(args[cur_arg + 1])) {
4330 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4331 file, linenum, args[0], args[1], ptr_arg);
4332 err_code |= ERR_ALERT | ERR_FATAL;
4333 goto out;
4334 }
4335 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004336 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004337 curproxy->expect_str = strdup(args[cur_arg + 1]);
4338 }
4339 else if (strcmp(ptr_arg, "rstatus") == 0) {
4340 if (!*(args[cur_arg + 1])) {
4341 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4342 file, linenum, args[0], args[1], ptr_arg);
4343 err_code |= ERR_ALERT | ERR_FATAL;
4344 goto out;
4345 }
4346 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004347 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004348 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004349 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004350 free(curproxy->expect_regex);
4351 curproxy->expect_regex = NULL;
4352 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004353 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004354 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4355 error = NULL;
4356 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4357 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4358 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4359 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004360 err_code |= ERR_ALERT | ERR_FATAL;
4361 goto out;
4362 }
4363 }
4364 else if (strcmp(ptr_arg, "rstring") == 0) {
4365 if (!*(args[cur_arg + 1])) {
4366 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4367 file, linenum, args[0], args[1], ptr_arg);
4368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
4370 }
4371 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004372 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004373 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004374 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004375 free(curproxy->expect_regex);
4376 curproxy->expect_regex = NULL;
4377 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004378 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004379 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4380 error = NULL;
4381 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4382 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4383 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4384 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004385 err_code |= ERR_ALERT | ERR_FATAL;
4386 goto out;
4387 }
4388 }
4389 else {
4390 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4391 file, linenum, args[0], args[1], ptr_arg);
4392 err_code |= ERR_ALERT | ERR_FATAL;
4393 goto out;
4394 }
4395 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004396 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004397 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 +02004398 err_code |= ERR_ALERT | ERR_FATAL;
4399 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004400 }
4401 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004402 else if (!strcmp(args[0], "tcp-check")) {
4403 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4404 err_code |= ERR_WARN;
4405
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004406 if (strcmp(args[1], "connect") == 0) {
4407 const char *ptr_arg;
4408 int cur_arg;
4409 struct tcpcheck_rule *tcpcheck;
4410 struct list *l;
4411
4412 /* check if first rule is also a 'connect' action */
4413 l = (struct list *)&curproxy->tcpcheck_rules;
4414 if (l->p != l->n) {
4415 tcpcheck = (struct tcpcheck_rule *)l->n;
4416 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4417 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4418 file, linenum);
4419 err_code |= ERR_ALERT | ERR_FATAL;
4420 goto out;
4421 }
4422 }
4423
4424 cur_arg = 2;
4425 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4426 tcpcheck->action = TCPCHK_ACT_CONNECT;
4427
4428 /* parsing each parameters to fill up the rule */
4429 while (*(ptr_arg = args[cur_arg])) {
4430 /* tcp port */
4431 if (strcmp(args[cur_arg], "port") == 0) {
4432 if ( (atol(args[cur_arg + 1]) > 65535) ||
4433 (atol(args[cur_arg + 1]) < 1) ){
4434 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4435 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4436 err_code |= ERR_ALERT | ERR_FATAL;
4437 goto out;
4438 }
4439 tcpcheck->port = atol(args[cur_arg + 1]);
4440 cur_arg += 2;
4441 }
4442 /* send proxy protocol */
4443 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4444 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4445 cur_arg++;
4446 }
4447#ifdef USE_OPENSSL
4448 else if (strcmp(args[cur_arg], "ssl") == 0) {
4449 curproxy->options |= PR_O_TCPCHK_SSL;
4450 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4451 cur_arg++;
4452 }
4453#endif /* USE_OPENSSL */
4454 else {
4455#ifdef USE_OPENSSL
4456 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4457#else /* USE_OPENSSL */
4458 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4459#endif /* USE_OPENSSL */
4460 file, linenum, args[0], args[1], args[cur_arg]);
4461 err_code |= ERR_ALERT | ERR_FATAL;
4462 goto out;
4463 }
4464
4465 }
4466
4467 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4468 }
4469 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004470 if (! *(args[2]) ) {
4471 /* SEND string expected */
4472 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4473 file, linenum, args[0], args[1], args[2]);
4474 err_code |= ERR_ALERT | ERR_FATAL;
4475 goto out;
4476 } else {
4477 struct tcpcheck_rule *tcpcheck;
4478
4479 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4480
4481 tcpcheck->action = TCPCHK_ACT_SEND;
4482 tcpcheck->string_len = strlen(args[2]);
4483 tcpcheck->string = strdup(args[2]);
4484 tcpcheck->expect_regex = NULL;
4485
4486 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4487 }
4488 }
4489 else if (strcmp(args[1], "send-binary") == 0) {
4490 if (! *(args[2]) ) {
4491 /* SEND binary string expected */
4492 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4493 file, linenum, args[0], args[1], args[2]);
4494 err_code |= ERR_ALERT | ERR_FATAL;
4495 goto out;
4496 } else {
4497 struct tcpcheck_rule *tcpcheck;
4498 char *err = NULL;
4499
4500 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4501
4502 tcpcheck->action = TCPCHK_ACT_SEND;
4503 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4504 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4505 file, linenum, args[0], args[1], args[2], err);
4506 err_code |= ERR_ALERT | ERR_FATAL;
4507 goto out;
4508 }
4509 tcpcheck->expect_regex = NULL;
4510
4511 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4512 }
4513 }
4514 else if (strcmp(args[1], "expect") == 0) {
4515 const char *ptr_arg;
4516 int cur_arg;
4517 int inverse = 0;
4518
4519 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4520 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4521 err_code |= ERR_ALERT | ERR_FATAL;
4522 goto out;
4523 }
4524
4525 cur_arg = 2;
4526 /* consider exclamation marks, sole or at the beginning of a word */
4527 while (*(ptr_arg = args[cur_arg])) {
4528 while (*ptr_arg == '!') {
4529 inverse = !inverse;
4530 ptr_arg++;
4531 }
4532 if (*ptr_arg)
4533 break;
4534 cur_arg++;
4535 }
4536 /* now ptr_arg points to the beginning of a word past any possible
4537 * exclamation mark, and cur_arg is the argument which holds this word.
4538 */
4539 if (strcmp(ptr_arg, "binary") == 0) {
4540 if (!*(args[cur_arg + 1])) {
4541 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4542 file, linenum, args[0], args[1], ptr_arg);
4543 err_code |= ERR_ALERT | ERR_FATAL;
4544 goto out;
4545 }
4546 struct tcpcheck_rule *tcpcheck;
4547 char *err = NULL;
4548
4549 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4550
4551 tcpcheck->action = TCPCHK_ACT_EXPECT;
4552 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4553 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4554 file, linenum, args[0], args[1], args[2], err);
4555 err_code |= ERR_ALERT | ERR_FATAL;
4556 goto out;
4557 }
4558 tcpcheck->expect_regex = NULL;
4559 tcpcheck->inverse = inverse;
4560
4561 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4562 }
4563 else if (strcmp(ptr_arg, "string") == 0) {
4564 if (!*(args[cur_arg + 1])) {
4565 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4566 file, linenum, args[0], args[1], ptr_arg);
4567 err_code |= ERR_ALERT | ERR_FATAL;
4568 goto out;
4569 }
4570 struct tcpcheck_rule *tcpcheck;
4571
4572 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4573
4574 tcpcheck->action = TCPCHK_ACT_EXPECT;
4575 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4576 tcpcheck->string = strdup(args[cur_arg + 1]);
4577 tcpcheck->expect_regex = NULL;
4578 tcpcheck->inverse = inverse;
4579
4580 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4581 }
4582 else if (strcmp(ptr_arg, "rstring") == 0) {
4583 if (!*(args[cur_arg + 1])) {
4584 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4585 file, linenum, args[0], args[1], ptr_arg);
4586 err_code |= ERR_ALERT | ERR_FATAL;
4587 goto out;
4588 }
4589 struct tcpcheck_rule *tcpcheck;
4590
4591 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4592
4593 tcpcheck->action = TCPCHK_ACT_EXPECT;
4594 tcpcheck->string_len = 0;
4595 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004596 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4597 error = NULL;
4598 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4599 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4600 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4601 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004602 err_code |= ERR_ALERT | ERR_FATAL;
4603 goto out;
4604 }
4605 tcpcheck->inverse = inverse;
4606
4607 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4608 }
4609 else {
4610 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4611 file, linenum, args[0], args[1], ptr_arg);
4612 err_code |= ERR_ALERT | ERR_FATAL;
4613 goto out;
4614 }
4615 }
4616 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004617 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004618 err_code |= ERR_ALERT | ERR_FATAL;
4619 goto out;
4620 }
4621 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004622 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +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 Tarreaub099aca2008-10-12 17:26:37 +02004627 }
4628
Willy Tarreaub80c2302007-11-30 20:51:32 +01004629 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004630 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004631
4632 if (strcmp(args[1], "fail") == 0) {
4633 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004634 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004635 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4636 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004639 }
4640
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004641 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4642 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4643 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004644 err_code |= ERR_ALERT | ERR_FATAL;
4645 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004646 }
4647 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4648 }
4649 else {
4650 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004651 err_code |= ERR_ALERT | ERR_FATAL;
4652 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004653 }
4654 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004655#ifdef TPROXY
4656 else if (!strcmp(args[0], "transparent")) {
4657 /* enable transparent proxy connections */
4658 curproxy->options |= PR_O_TRANSP;
4659 }
4660#endif
4661 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004662 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004663 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004664
Willy Tarreaubaaee002006-06-26 02:48:02 +02004665 if (*(args[1]) == 0) {
4666 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004669 }
4670 curproxy->maxconn = atol(args[1]);
4671 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004672 else if (!strcmp(args[0], "backlog")) { /* backlog */
4673 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004674 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004675
4676 if (*(args[1]) == 0) {
4677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004678 err_code |= ERR_ALERT | ERR_FATAL;
4679 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004680 }
4681 curproxy->backlog = atol(args[1]);
4682 }
Willy Tarreau86034312006-12-29 00:10:33 +01004683 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004684 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004685 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004686
Willy Tarreau86034312006-12-29 00:10:33 +01004687 if (*(args[1]) == 0) {
4688 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004689 err_code |= ERR_ALERT | ERR_FATAL;
4690 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004691 }
4692 curproxy->fullconn = atol(args[1]);
4693 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004694 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4695 if (*(args[1]) == 0) {
4696 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004697 err_code |= ERR_ALERT | ERR_FATAL;
4698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004699 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004700 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4701 if (err) {
4702 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4703 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004704 err_code |= ERR_ALERT | ERR_FATAL;
4705 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004706 }
4707 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004708 }
4709 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004710 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004711 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004712 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004713
Willy Tarreaubaaee002006-06-26 02:48:02 +02004714 if (curproxy == &defproxy) {
4715 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004716 err_code |= ERR_ALERT | ERR_FATAL;
4717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004718 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004719 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004720 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004721
Willy Tarreau902636f2013-03-10 19:44:48 +01004722 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004723 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004724 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004725 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004726 goto out;
4727 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004728
4729 proto = protocol_by_family(sk->ss_family);
4730 if (!proto || !proto->connect) {
4731 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4732 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004733 err_code |= ERR_ALERT | ERR_FATAL;
4734 goto out;
4735 }
4736
4737 if (port1 != port2) {
4738 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4739 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004740 err_code |= ERR_ALERT | ERR_FATAL;
4741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004742 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004743
4744 if (!port1) {
4745 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4746 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004747 err_code |= ERR_ALERT | ERR_FATAL;
4748 goto out;
4749 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004750
Willy Tarreaud5191e72010-02-09 20:50:45 +01004751 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004752 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004753 }
4754 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004755 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004756 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004757
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004758 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4759 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004760 err_code |= ERR_ALERT | ERR_FATAL;
4761 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004762 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004764 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004765 /**
4766 * The syntax for hash-type config element is
4767 * hash-type {map-based|consistent} [[<algo>] avalanche]
4768 *
4769 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4770 */
4771 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004772
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004773 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4774 err_code |= ERR_WARN;
4775
4776 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004777 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4778 }
4779 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004780 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4781 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004782 else if (strcmp(args[1], "avalanche") == 0) {
4783 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]);
4784 err_code |= ERR_ALERT | ERR_FATAL;
4785 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004786 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004787 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004788 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004789 err_code |= ERR_ALERT | ERR_FATAL;
4790 goto out;
4791 }
Bhaskar98634f02013-10-29 23:30:51 -04004792
4793 /* set the hash function to use */
4794 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004795 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004796 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004797
4798 /* if consistent with no argument, then avalanche modifier is also applied */
4799 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4800 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004801 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004802 /* set the hash function */
4803 if (!strcmp(args[2], "sdbm")) {
4804 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4805 }
4806 else if (!strcmp(args[2], "djb2")) {
4807 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004808 } else if (!strcmp(args[2], "wt6")) {
4809 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004810 }
4811 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004812 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 -05004813 err_code |= ERR_ALERT | ERR_FATAL;
4814 goto out;
4815 }
4816
4817 /* set the hash modifier */
4818 if (!strcmp(args[3], "avalanche")) {
4819 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4820 }
4821 else if (*args[3]) {
4822 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4823 err_code |= ERR_ALERT | ERR_FATAL;
4824 goto out;
4825 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004826 }
William Lallemanda73203e2012-03-12 12:48:57 +01004827 }
William Lallemanda73203e2012-03-12 12:48:57 +01004828 else if (strcmp(args[0], "unique-id-format") == 0) {
4829 if (!*(args[1])) {
4830 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4831 err_code |= ERR_ALERT | ERR_FATAL;
4832 goto out;
4833 }
William Lallemand3203ff42012-11-11 17:30:56 +01004834 if (*(args[2])) {
4835 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4836 err_code |= ERR_ALERT | ERR_FATAL;
4837 goto out;
4838 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004839 free(curproxy->conf.uniqueid_format_string);
4840 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004841
Willy Tarreau62a61232013-04-12 18:13:46 +02004842 free(curproxy->conf.uif_file);
4843 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4844 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004845 }
William Lallemanda73203e2012-03-12 12:48:57 +01004846
4847 else if (strcmp(args[0], "unique-id-header") == 0) {
4848 if (!*(args[1])) {
4849 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4850 err_code |= ERR_ALERT | ERR_FATAL;
4851 goto out;
4852 }
4853 free(curproxy->header_unique_id);
4854 curproxy->header_unique_id = strdup(args[1]);
4855 }
4856
William Lallemand723b73a2012-02-08 16:37:49 +01004857 else if (strcmp(args[0], "log-format") == 0) {
4858 if (!*(args[1])) {
4859 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
4862 }
William Lallemand3203ff42012-11-11 17:30:56 +01004863 if (*(args[2])) {
4864 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4865 err_code |= ERR_ALERT | ERR_FATAL;
4866 goto out;
4867 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004868
Willy Tarreau62a61232013-04-12 18:13:46 +02004869 if (curproxy->conf.logformat_string != default_http_log_format &&
4870 curproxy->conf.logformat_string != default_tcp_log_format &&
4871 curproxy->conf.logformat_string != clf_http_log_format)
4872 free(curproxy->conf.logformat_string);
4873 curproxy->conf.logformat_string = strdup(args[1]);
4874
4875 free(curproxy->conf.lfs_file);
4876 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4877 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004878
4879 /* get a chance to improve log-format error reporting by
4880 * reporting the correct line-number when possible.
4881 */
4882 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4883 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4884 file, linenum, curproxy->id);
4885 err_code |= ERR_WARN;
4886 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004887 }
William Lallemand723b73a2012-02-08 16:37:49 +01004888
William Lallemand0f99e342011-10-12 17:50:54 +02004889 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4890 /* delete previous herited or defined syslog servers */
4891 struct logsrv *back;
4892
4893 if (*(args[1]) != 0) {
4894 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4895 err_code |= ERR_ALERT | ERR_FATAL;
4896 goto out;
4897 }
4898
William Lallemand723b73a2012-02-08 16:37:49 +01004899 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4900 LIST_DEL(&tmplogsrv->list);
4901 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004902 }
4903 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004904 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004905 struct logsrv *logsrv;
4906
Willy Tarreaubaaee002006-06-26 02:48:02 +02004907 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004908 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004909 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004910 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004911 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004912 LIST_INIT(&node->list);
4913 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4914 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004915 }
4916 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004917 struct sockaddr_storage *sk;
4918 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02004919 int arg = 0;
4920 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004921
4922 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004923
Willy Tarreau18324f52014-06-27 18:10:07 +02004924 /* just after the address, a length may be specified */
4925 if (strcmp(args[arg+2], "len") == 0) {
4926 len = atoi(args[arg+3]);
4927 if (len < 80 || len > 65535) {
4928 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4929 file, linenum, args[arg+3]);
4930 err_code |= ERR_ALERT | ERR_FATAL;
4931 goto out;
4932 }
4933 logsrv->maxlen = len;
4934
4935 /* skip these two args */
4936 arg += 2;
4937 }
4938 else
4939 logsrv->maxlen = MAX_SYSLOG_LEN;
4940
4941 if (logsrv->maxlen > global.max_syslog_len) {
4942 global.max_syslog_len = logsrv->maxlen;
4943 logline = realloc(logline, global.max_syslog_len + 1);
4944 }
4945
4946 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004947 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004948 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004949 err_code |= ERR_ALERT | ERR_FATAL;
4950 goto out;
4951
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 }
4953
William Lallemand0f99e342011-10-12 17:50:54 +02004954 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02004955 if (*(args[arg+3])) {
4956 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004957 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004958 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004959 err_code |= ERR_ALERT | ERR_FATAL;
4960 goto out;
4961
Willy Tarreaubaaee002006-06-26 02:48:02 +02004962 }
4963 }
4964
William Lallemand0f99e342011-10-12 17:50:54 +02004965 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02004966 if (*(args[arg+4])) {
4967 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004968 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004969 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004970 err_code |= ERR_ALERT | ERR_FATAL;
4971 goto out;
4972
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004973 }
4974 }
4975
Willy Tarreau902636f2013-03-10 19:44:48 +01004976 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004977 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004978 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004979 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004980 goto out;
4981 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004982
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004983 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004984
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004985 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004986 if (port1 != port2) {
4987 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4988 file, linenum, args[0], args[1]);
4989 err_code |= ERR_ALERT | ERR_FATAL;
4990 goto out;
4991 }
4992
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004993 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004994 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004995 }
William Lallemand0f99e342011-10-12 17:50:54 +02004996
4997 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004998 }
4999 else {
5000 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5001 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005002 err_code |= ERR_ALERT | ERR_FATAL;
5003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005004 }
5005 }
5006 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005007 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005008 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005009 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005010 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005011
Willy Tarreau977b8e42006-12-29 14:19:17 +01005012 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005013 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005014
Willy Tarreaubaaee002006-06-26 02:48:02 +02005015 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005016 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5017 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005018 err_code |= ERR_ALERT | ERR_FATAL;
5019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005021
5022 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005023 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5024 free(curproxy->conn_src.iface_name);
5025 curproxy->conn_src.iface_name = NULL;
5026 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005027
Willy Tarreau902636f2013-03-10 19:44:48 +01005028 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005029 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005030 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005031 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005032 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005033 goto out;
5034 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005035
5036 proto = protocol_by_family(sk->ss_family);
5037 if (!proto || !proto->connect) {
5038 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005039 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005040 err_code |= ERR_ALERT | ERR_FATAL;
5041 goto out;
5042 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005043
5044 if (port1 != port2) {
5045 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5046 file, linenum, args[0], args[1]);
5047 err_code |= ERR_ALERT | ERR_FATAL;
5048 goto out;
5049 }
5050
Willy Tarreauef9a3602012-12-08 22:29:20 +01005051 curproxy->conn_src.source_addr = *sk;
5052 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005053
5054 cur_arg = 2;
5055 while (*(args[cur_arg])) {
5056 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005057#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5058#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005059 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005060 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5061 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 }
5065#endif
5066 if (!*args[cur_arg + 1]) {
5067 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5068 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005069 err_code |= ERR_ALERT | ERR_FATAL;
5070 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005071 }
5072
5073 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005074 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5075 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005076 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005077 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5078 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005079 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5080 char *name, *end;
5081
5082 name = args[cur_arg+1] + 7;
5083 while (isspace(*name))
5084 name++;
5085
5086 end = name;
5087 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5088 end++;
5089
Willy Tarreauef9a3602012-12-08 22:29:20 +01005090 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5091 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5092 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5093 curproxy->conn_src.bind_hdr_len = end - name;
5094 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5095 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5096 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005097
5098 /* now look for an occurrence number */
5099 while (isspace(*end))
5100 end++;
5101 if (*end == ',') {
5102 end++;
5103 name = end;
5104 if (*end == '-')
5105 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005106 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005107 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005108 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005109 }
5110
Willy Tarreauef9a3602012-12-08 22:29:20 +01005111 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005112 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5113 " occurrences values smaller than %d.\n",
5114 file, linenum, MAX_HDR_HISTORY);
5115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
5117 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005118 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005119 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005120
Willy Tarreau902636f2013-03-10 19:44:48 +01005121 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005122 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005123 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005124 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005125 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005126 goto out;
5127 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005128
5129 proto = protocol_by_family(sk->ss_family);
5130 if (!proto || !proto->connect) {
5131 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5132 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005133 err_code |= ERR_ALERT | ERR_FATAL;
5134 goto out;
5135 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005136
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005137 if (port1 != port2) {
5138 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5139 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005140 err_code |= ERR_ALERT | ERR_FATAL;
5141 goto out;
5142 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005143 curproxy->conn_src.tproxy_addr = *sk;
5144 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005145 }
5146 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005147#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005148 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005149#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005150#else /* no TPROXY support */
5151 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005152 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005153 err_code |= ERR_ALERT | ERR_FATAL;
5154 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005155#endif
5156 cur_arg += 2;
5157 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005158 }
5159
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005160 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5161#ifdef SO_BINDTODEVICE
5162 if (!*args[cur_arg + 1]) {
5163 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5164 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005165 err_code |= ERR_ALERT | ERR_FATAL;
5166 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005167 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005168 free(curproxy->conn_src.iface_name);
5169 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5170 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005171 global.last_checks |= LSTCHK_NETADM;
5172#else
5173 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5174 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005175 err_code |= ERR_ALERT | ERR_FATAL;
5176 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005177#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005178 cur_arg += 2;
5179 continue;
5180 }
5181 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005182 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005185 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005186 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005187 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5188 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5189 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005190 err_code |= ERR_ALERT | ERR_FATAL;
5191 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005192 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005193 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005194 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005195 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5196 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005197 err_code |= ERR_ALERT | ERR_FATAL;
5198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005200
5201 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005202 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005203 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005204 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005206 }
5207 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005208 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005209 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005210 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005211 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005213 }
5214 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005215 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005216 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005217 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005218 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005219 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005220 }
5221 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005222 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005223 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005224 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005225 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005227 }
5228 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005229 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005230 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005231 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005232 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005234 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005235 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005236 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005237 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005238 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005239 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005240 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005241 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005242 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005243 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005244 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005245 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005246 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005247 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005248
5249 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5250 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 +01005251 }
5252 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005253 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005254 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005255 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005256 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005257 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005258
5259 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5260 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 +01005261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005262 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005263 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005264 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5265 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005266 err_code |= ERR_ALERT | ERR_FATAL;
5267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005268 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005269
5270 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005271 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005272 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005273 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005274 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005275 }
5276 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005277 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005278 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005279 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005280 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005282 }
5283 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005284 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005285 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005286 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005287 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005289 }
5290 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005291 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005292 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005293 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005294 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296 }
5297 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005298 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005299 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005300 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005301 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005303 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005304 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005305 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005306 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005307 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005308 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005309 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005310 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005311 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005312 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005313
Willy Tarreaubaaee002006-06-26 02:48:02 +02005314 if (curproxy == &defproxy) {
5315 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005316 err_code |= ERR_ALERT | ERR_FATAL;
5317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005318 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005319 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005320 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321
Willy Tarreaubaaee002006-06-26 02:48:02 +02005322 if (*(args[1]) == 0) {
5323 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005324 err_code |= ERR_ALERT | ERR_FATAL;
5325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005327
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005328 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005329 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5330 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5331 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005332 err_code |= ERR_ALERT | ERR_FATAL;
5333 goto out;
5334 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005335 err_code |= warnif_cond_conflicts(cond,
5336 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5337 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005338 }
5339 else if (*args[2]) {
5340 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5341 file, linenum, args[0], args[2]);
5342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
5344 }
5345
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005346 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005347 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005348 wl->s = strdup(args[1]);
5349 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005350 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005351 }
5352 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005353 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005354 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5355 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005356 err_code |= ERR_ALERT | ERR_FATAL;
5357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005358 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005359
Willy Tarreauade5ec42010-01-28 19:33:49 +01005360 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005361 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005362 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005363 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005365 }
5366 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005367 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005368 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005369 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005370 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005372 }
5373 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005374 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005375 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005376 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005377 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005379 }
5380 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005381 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005382 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5383 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005384 err_code |= ERR_ALERT | ERR_FATAL;
5385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005386 }
5387
Willy Tarreauade5ec42010-01-28 19:33:49 +01005388 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005389 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005390 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005391 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005393 }
5394 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005395 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005396 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005397 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005398 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005400 }
5401 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005402 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005403 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005404 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005405 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005407 }
5408 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005409 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005410
Willy Tarreaubaaee002006-06-26 02:48:02 +02005411 if (curproxy == &defproxy) {
5412 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005413 err_code |= ERR_ALERT | ERR_FATAL;
5414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005415 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005416 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005417 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005418
Willy Tarreaubaaee002006-06-26 02:48:02 +02005419 if (*(args[1]) == 0) {
5420 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005421 err_code |= ERR_ALERT | ERR_FATAL;
5422 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005423 }
5424
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005425 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005426 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5427 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5428 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005429 err_code |= ERR_ALERT | ERR_FATAL;
5430 goto out;
5431 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005432 err_code |= warnif_cond_conflicts(cond,
5433 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5434 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005435 }
5436 else if (*args[2]) {
5437 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5438 file, linenum, args[0], args[2]);
5439 err_code |= ERR_ALERT | ERR_FATAL;
5440 goto out;
5441 }
5442
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005443 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005444 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005445 wl->s = strdup(args[1]);
5446 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005447 }
5448 else if (!strcmp(args[0], "errorloc") ||
5449 !strcmp(args[0], "errorloc302") ||
5450 !strcmp(args[0], "errorloc303")) { /* error location */
5451 int errnum, errlen;
5452 char *err;
5453
Willy Tarreau977b8e42006-12-29 14:19:17 +01005454 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005455 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005456
Willy Tarreaubaaee002006-06-26 02:48:02 +02005457 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005458 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005459 err_code |= ERR_ALERT | ERR_FATAL;
5460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005461 }
5462
5463 errnum = atol(args[1]);
5464 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005465 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5466 err = malloc(errlen);
5467 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005469 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5470 err = malloc(errlen);
5471 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005472 }
5473
Willy Tarreau0f772532006-12-23 20:51:41 +01005474 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5475 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005476 chunk_destroy(&curproxy->errmsg[rc]);
5477 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005478 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005480 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005481
5482 if (rc >= HTTP_ERR_SIZE) {
5483 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5484 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005485 free(err);
5486 }
5487 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005488 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5489 int errnum, errlen, fd;
5490 char *err;
5491 struct stat stat;
5492
5493 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005494 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005495
5496 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005497 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005498 err_code |= ERR_ALERT | ERR_FATAL;
5499 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005500 }
5501
5502 fd = open(args[2], O_RDONLY);
5503 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5504 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5505 file, linenum, args[2], args[1]);
5506 if (fd >= 0)
5507 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005508 err_code |= ERR_ALERT | ERR_FATAL;
5509 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005510 }
5511
Willy Tarreau27a674e2009-08-17 07:23:33 +02005512 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005513 errlen = stat.st_size;
5514 } else {
5515 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005516 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005517 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005518 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005519 }
5520
5521 err = malloc(errlen); /* malloc() must succeed during parsing */
5522 errnum = read(fd, err, errlen);
5523 if (errnum != errlen) {
5524 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5525 file, linenum, args[2], args[1]);
5526 close(fd);
5527 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005528 err_code |= ERR_ALERT | ERR_FATAL;
5529 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005530 }
5531 close(fd);
5532
5533 errnum = atol(args[1]);
5534 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5535 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005536 chunk_destroy(&curproxy->errmsg[rc]);
5537 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005538 break;
5539 }
5540 }
5541
5542 if (rc >= HTTP_ERR_SIZE) {
5543 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5544 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005545 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005546 free(err);
5547 }
5548 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005549 else if (!strcmp(args[0], "compression")) {
5550 struct comp *comp;
5551 if (curproxy->comp == NULL) {
5552 comp = calloc(1, sizeof(struct comp));
5553 curproxy->comp = comp;
5554 } else {
5555 comp = curproxy->comp;
5556 }
5557
5558 if (!strcmp(args[1], "algo")) {
5559 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005560 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005561
William Lallemand82fe75c2012-10-23 10:25:10 +02005562 cur_arg = 2;
5563 if (!*args[cur_arg]) {
5564 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5565 file, linenum, args[0]);
5566 err_code |= ERR_ALERT | ERR_FATAL;
5567 goto out;
5568 }
5569 while (*(args[cur_arg])) {
5570 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5571 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5572 file, linenum, args[0], args[cur_arg]);
5573 err_code |= ERR_ALERT | ERR_FATAL;
5574 goto out;
5575 }
William Lallemand552df672012-11-07 13:21:47 +01005576 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5577 curproxy->comp->algos->end(&ctx);
5578 } else {
5579 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5580 file, linenum, args[0], args[cur_arg]);
5581 err_code |= ERR_ALERT | ERR_FATAL;
5582 goto out;
5583 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005584 cur_arg ++;
5585 continue;
5586 }
5587 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005588 else if (!strcmp(args[1], "offload")) {
5589 comp->offload = 1;
5590 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005591 else if (!strcmp(args[1], "type")) {
5592 int cur_arg;
5593 cur_arg = 2;
5594 if (!*args[cur_arg]) {
5595 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5596 file, linenum, args[0]);
5597 err_code |= ERR_ALERT | ERR_FATAL;
5598 goto out;
5599 }
5600 while (*(args[cur_arg])) {
5601 comp_append_type(comp, args[cur_arg]);
5602 cur_arg ++;
5603 continue;
5604 }
5605 }
5606 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005607 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005608 file, linenum, args[0]);
5609 err_code |= ERR_ALERT | ERR_FATAL;
5610 goto out;
5611 }
5612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005613 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005614 struct cfg_kw_list *kwl;
5615 int index;
5616
5617 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5618 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5619 if (kwl->kw[index].section != CFG_LISTEN)
5620 continue;
5621 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5622 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005623 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005624 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005625 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005626 err_code |= ERR_ALERT | ERR_FATAL;
5627 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005628 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005629 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005630 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005631 err_code |= ERR_WARN;
5632 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005633 }
Willy Tarreau93893792009-07-23 13:19:11 +02005634 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005635 }
5636 }
5637 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005638
Willy Tarreau6daf3432008-01-22 16:44:08 +01005639 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005640 err_code |= ERR_ALERT | ERR_FATAL;
5641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005642 }
Willy Tarreau93893792009-07-23 13:19:11 +02005643 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005644 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005645 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005646}
5647
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005648int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005649cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
5650{
5651#ifdef CONFIG_HAP_NS
5652 const char *err;
5653 const char *item = args[0];
5654
5655 if (!strcmp(item, "namespace_list")) {
5656 return 0;
5657 }
5658 else if (!strcmp(item, "namespace")) {
5659 size_t idx = 1;
5660 const char *current;
5661 while (*(current = args[idx++])) {
5662 err = invalid_char(current);
5663 if (err) {
5664 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5665 file, linenum, *err, item, current);
5666 return ERR_ALERT | ERR_FATAL;
5667 }
5668
5669 if (netns_store_lookup(current, strlen(current))) {
5670 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
5671 file, linenum, current);
5672 return ERR_ALERT | ERR_FATAL;
5673 }
5674 if (!netns_store_insert(current)) {
5675 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
5676 file, linenum, current);
5677 return ERR_ALERT | ERR_FATAL;
5678 }
5679 }
5680 }
5681
5682 return 0;
5683#else
5684 Alert("parsing [%s:%d]: namespace support is not compiled in.",
5685 file, linenum);
5686 return ERR_ALERT | ERR_FATAL;
5687#endif
5688}
5689
5690int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005691cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5692{
5693
5694 int err_code = 0;
5695 const char *err;
5696
5697 if (!strcmp(args[0], "userlist")) { /* new userlist */
5698 struct userlist *newul;
5699
5700 if (!*args[1]) {
5701 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5702 file, linenum, args[0]);
5703 err_code |= ERR_ALERT | ERR_FATAL;
5704 goto out;
5705 }
5706
5707 err = invalid_char(args[1]);
5708 if (err) {
5709 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5710 file, linenum, *err, args[0], args[1]);
5711 err_code |= ERR_ALERT | ERR_FATAL;
5712 goto out;
5713 }
5714
5715 for (newul = userlist; newul; newul = newul->next)
5716 if (!strcmp(newul->name, args[1])) {
5717 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5718 file, linenum, args[1]);
5719 err_code |= ERR_WARN;
5720 goto out;
5721 }
5722
5723 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5724 if (!newul) {
5725 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5726 err_code |= ERR_ALERT | ERR_ABORT;
5727 goto out;
5728 }
5729
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005730 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005731 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005732 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5733 err_code |= ERR_ALERT | ERR_ABORT;
5734 goto out;
5735 }
5736
5737 newul->next = userlist;
5738 userlist = newul;
5739
5740 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005741 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005742 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005743 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005744
5745 if (!*args[1]) {
5746 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5747 file, linenum, args[0]);
5748 err_code |= ERR_ALERT | ERR_FATAL;
5749 goto out;
5750 }
5751
5752 err = invalid_char(args[1]);
5753 if (err) {
5754 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5755 file, linenum, *err, args[0], args[1]);
5756 err_code |= ERR_ALERT | ERR_FATAL;
5757 goto out;
5758 }
5759
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005760 for (ag = userlist->groups; ag; ag = ag->next)
5761 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005762 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5763 file, linenum, args[1], userlist->name);
5764 err_code |= ERR_ALERT;
5765 goto out;
5766 }
5767
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005768 ag = calloc(1, sizeof(*ag));
5769 if (!ag) {
5770 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5771 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005772 goto out;
5773 }
5774
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005775 ag->name = strdup(args[1]);
5776 if (!ag) {
5777 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5778 err_code |= ERR_ALERT | ERR_ABORT;
5779 goto out;
5780 }
5781
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005782 cur_arg = 2;
5783
5784 while (*args[cur_arg]) {
5785 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005786 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005787 cur_arg += 2;
5788 continue;
5789 } else {
5790 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5791 file, linenum, args[0]);
5792 err_code |= ERR_ALERT | ERR_FATAL;
5793 goto out;
5794 }
5795 }
5796
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005797 ag->next = userlist->groups;
5798 userlist->groups = ag;
5799
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005800 } else if (!strcmp(args[0], "user")) { /* new user */
5801 struct auth_users *newuser;
5802 int cur_arg;
5803
5804 if (!*args[1]) {
5805 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5806 file, linenum, args[0]);
5807 err_code |= ERR_ALERT | ERR_FATAL;
5808 goto out;
5809 }
5810
5811 for (newuser = userlist->users; newuser; newuser = newuser->next)
5812 if (!strcmp(newuser->user, args[1])) {
5813 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5814 file, linenum, args[1], userlist->name);
5815 err_code |= ERR_ALERT;
5816 goto out;
5817 }
5818
5819 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5820 if (!newuser) {
5821 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5822 err_code |= ERR_ALERT | ERR_ABORT;
5823 goto out;
5824 }
5825
5826 newuser->user = strdup(args[1]);
5827
5828 newuser->next = userlist->users;
5829 userlist->users = newuser;
5830
5831 cur_arg = 2;
5832
5833 while (*args[cur_arg]) {
5834 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02005835#ifdef CONFIG_HAP_CRYPT
5836 if (!crypt("", args[cur_arg + 1])) {
5837 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
5838 file, linenum, newuser->user);
5839 err_code |= ERR_ALERT | ERR_FATAL;
5840 goto out;
5841 }
5842#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005843 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5844 file, linenum);
5845 err_code |= ERR_ALERT;
5846#endif
5847 newuser->pass = strdup(args[cur_arg + 1]);
5848 cur_arg += 2;
5849 continue;
5850 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5851 newuser->pass = strdup(args[cur_arg + 1]);
5852 newuser->flags |= AU_O_INSECURE;
5853 cur_arg += 2;
5854 continue;
5855 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005856 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005857 cur_arg += 2;
5858 continue;
5859 } else {
5860 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5861 file, linenum, args[0]);
5862 err_code |= ERR_ALERT | ERR_FATAL;
5863 goto out;
5864 }
5865 }
5866 } else {
5867 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5868 err_code |= ERR_ALERT | ERR_FATAL;
5869 }
5870
5871out:
5872 return err_code;
5873}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005874
5875/*
5876 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005877 * Returns the error code, 0 if OK, or any combination of :
5878 * - ERR_ABORT: must abort ASAP
5879 * - ERR_FATAL: we can continue parsing but not start the service
5880 * - ERR_WARN: a warning has been emitted
5881 * - ERR_ALERT: an alert has been emitted
5882 * Only the two first ones can stop processing, the two others are just
5883 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005884 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005885int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005886{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005887 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005888 FILE *f;
5889 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005890 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005891 struct cfg_section *cs = NULL;
5892 struct cfg_section *ics;
5893
5894 /* Register internal sections */
5895 if (!cfg_register_section("listen", cfg_parse_listen) ||
5896 !cfg_register_section("frontend", cfg_parse_listen) ||
5897 !cfg_register_section("backend", cfg_parse_listen) ||
5898 !cfg_register_section("ruleset", cfg_parse_listen) ||
5899 !cfg_register_section("defaults", cfg_parse_listen) ||
5900 !cfg_register_section("global", cfg_parse_global) ||
5901 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005902 !cfg_register_section("peers", cfg_parse_peers) ||
5903 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005904 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005905
Willy Tarreaubaaee002006-06-26 02:48:02 +02005906 if ((f=fopen(file,"r")) == NULL)
5907 return -1;
5908
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005909 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005910 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005911 char *end;
5912 char *args[MAX_LINE_ARGS + 1];
5913 char *line = thisline;
5914
Willy Tarreaubaaee002006-06-26 02:48:02 +02005915 linenum++;
5916
5917 end = line + strlen(line);
5918
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005919 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5920 /* Check if we reached the limit and the last char is not \n.
5921 * Watch out for the last line without the terminating '\n'!
5922 */
5923 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005924 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005925 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005926 }
5927
Willy Tarreaubaaee002006-06-26 02:48:02 +02005928 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005929 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005930 line++;
5931
5932 arg = 0;
5933 args[arg] = line;
5934
5935 while (*line && arg < MAX_LINE_ARGS) {
5936 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5937 * C equivalent value. Other combinations left unchanged (eg: \1).
5938 */
5939 if (*line == '\\') {
5940 int skip = 0;
5941 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5942 *line = line[1];
5943 skip = 1;
5944 }
5945 else if (line[1] == 'r') {
5946 *line = '\r';
5947 skip = 1;
5948 }
5949 else if (line[1] == 'n') {
5950 *line = '\n';
5951 skip = 1;
5952 }
5953 else if (line[1] == 't') {
5954 *line = '\t';
5955 skip = 1;
5956 }
5957 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005958 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005959 unsigned char hex1, hex2;
5960 hex1 = toupper(line[2]) - '0';
5961 hex2 = toupper(line[3]) - '0';
5962 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5963 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5964 *line = (hex1<<4) + hex2;
5965 skip = 3;
5966 }
5967 else {
5968 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005969 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005970 }
5971 }
5972 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005973 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005974 end -= skip;
5975 }
5976 line++;
5977 }
5978 else if (*line == '#' || *line == '\n' || *line == '\r') {
5979 /* end of string, end of loop */
5980 *line = 0;
5981 break;
5982 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005983 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005984 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005985 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005986 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005987 line++;
5988 args[++arg] = line;
5989 }
5990 else {
5991 line++;
5992 }
5993 }
5994
5995 /* empty line */
5996 if (!**args)
5997 continue;
5998
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005999 if (*line) {
6000 /* we had to stop due to too many args.
6001 * Let's terminate the string, print the offending part then cut the
6002 * last arg.
6003 */
6004 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6005 line++;
6006 *line = '\0';
6007
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006008 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006009 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006010 err_code |= ERR_ALERT | ERR_FATAL;
6011 args[arg] = line;
6012 }
6013
Willy Tarreau540abe42007-05-02 20:50:16 +02006014 /* zero out remaining args and ensure that at least one entry
6015 * is zeroed out.
6016 */
6017 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006018 args[arg] = line;
6019 }
6020
Willy Tarreau3842f002009-06-14 11:39:52 +02006021 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006022 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006023 char *tmp;
6024
Willy Tarreau3842f002009-06-14 11:39:52 +02006025 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006026 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006027 for (arg=0; *args[arg+1]; arg++)
6028 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006029 *tmp = '\0'; // fix the next arg to \0
6030 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006031 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006032 else if (!strcmp(args[0], "default")) {
6033 kwm = KWM_DEF;
6034 for (arg=0; *args[arg+1]; arg++)
6035 args[arg] = args[arg+1]; // shift args after inversion
6036 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006037
William Lallemand0f99e342011-10-12 17:50:54 +02006038 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6039 strcmp(args[0], "log") != 0) {
6040 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006041 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006042 }
6043
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006044 /* detect section start */
6045 list_for_each_entry(ics, &sections, list) {
6046 if (strcmp(args[0], ics->section_name) == 0) {
6047 cursection = ics->section_name;
6048 cs = ics;
6049 break;
6050 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006051 }
6052
Willy Tarreaubaaee002006-06-26 02:48:02 +02006053 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006054 if (cs)
6055 err_code |= cs->section_parser(file, linenum, args, kwm);
6056 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006057 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006058 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006059 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006060
6061 if (err_code & ERR_ABORT)
6062 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006063 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006064 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006065 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006066 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006067}
6068
Willy Tarreau64ab6072014-09-16 12:17:36 +02006069/* This function propagates processes from frontend <from> to backend <to> so
6070 * that it is always guaranteed that a backend pointed to by a frontend is
6071 * bound to all of its processes. After that, if the target is a "listen"
6072 * instance, the function recursively descends the target's own targets along
6073 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6074 * checked first to ensure that <to> is already bound to all processes of
6075 * <from>, there is no risk of looping and we ensure to follow the shortest
6076 * path to the destination.
6077 *
6078 * It is possible to set <to> to NULL for the first call so that the function
6079 * takes care of visiting the initial frontend in <from>.
6080 *
6081 * It is important to note that the function relies on the fact that all names
6082 * have already been resolved.
6083 */
6084void propagate_processes(struct proxy *from, struct proxy *to)
6085{
6086 struct switching_rule *rule;
6087 struct hdr_exp *exp;
6088
6089 if (to) {
6090 /* check whether we need to go down */
6091 if (from->bind_proc &&
6092 (from->bind_proc & to->bind_proc) == from->bind_proc)
6093 return;
6094
6095 if (!from->bind_proc && !to->bind_proc)
6096 return;
6097
6098 to->bind_proc = from->bind_proc ?
6099 (to->bind_proc | from->bind_proc) : 0;
6100
6101 /* now propagate down */
6102 from = to;
6103 }
6104
6105 if (!from->cap & PR_CAP_FE)
6106 return;
6107
6108 /* default_backend */
6109 if (from->defbe.be)
6110 propagate_processes(from, from->defbe.be);
6111
6112 /* use_backend */
6113 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006114 if (rule->dynamic)
6115 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006116 to = rule->be.backend;
6117 propagate_processes(from, to);
6118 }
6119
6120 /* reqsetbe */
6121 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6122 if (exp->action != ACT_SETBE)
6123 continue;
6124 to = (struct proxy *)exp->replace;
6125 propagate_processes(from, to);
6126 }
6127}
6128
Willy Tarreaubb925012009-07-23 13:36:36 +02006129/*
6130 * Returns the error code, 0 if OK, or any combination of :
6131 * - ERR_ABORT: must abort ASAP
6132 * - ERR_FATAL: we can continue parsing but not start the service
6133 * - ERR_WARN: a warning has been emitted
6134 * - ERR_ALERT: an alert has been emitted
6135 * Only the two first ones can stop processing, the two others are just
6136 * indicators.
6137 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006138int check_config_validity()
6139{
6140 int cfgerr = 0;
6141 struct proxy *curproxy = NULL;
6142 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006143 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006144 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006145 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006146
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006147 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006148 /*
6149 * Now, check for the integrity of all that we have collected.
6150 */
6151
6152 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006153 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006154
Willy Tarreau193b8c62012-11-22 00:17:38 +01006155 if (!global.tune.max_http_hdr)
6156 global.tune.max_http_hdr = MAX_HTTP_HDR;
6157
6158 if (!global.tune.cookie_len)
6159 global.tune.cookie_len = CAPTURE_LEN;
6160
6161 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6162
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006163 /* Post initialisation of the users and groups lists. */
6164 err_code = userlist_postinit();
6165 if (err_code != ERR_NONE)
6166 goto out;
6167
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006168 /* first, we will invert the proxy list order */
6169 curproxy = NULL;
6170 while (proxy) {
6171 struct proxy *next;
6172
6173 next = proxy->next;
6174 proxy->next = curproxy;
6175 curproxy = proxy;
6176 if (!next)
6177 break;
6178 proxy = next;
6179 }
6180
Willy Tarreau419ead82014-09-16 13:41:21 +02006181 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006182 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006183 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006184 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006185 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006186 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006187 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006188 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006189
Willy Tarreau050536d2012-10-04 08:47:34 +02006190 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006191 /* proxy ID not set, use automatic numbering with first
6192 * spare entry starting with next_pxid.
6193 */
6194 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6195 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6196 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006197 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006198 next_pxid++;
6199
Willy Tarreau55ea7572007-06-17 19:56:27 +02006200
Willy Tarreaubaaee002006-06-26 02:48:02 +02006201 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006202 /* ensure we don't keep listeners uselessly bound */
6203 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006204 continue;
6205 }
6206
Willy Tarreau102df612014-05-07 23:56:38 +02006207 /* Check multi-process mode compatibility for the current proxy */
6208
6209 if (curproxy->bind_proc) {
6210 /* an explicit bind-process was specified, let's check how many
6211 * processes remain.
6212 */
6213 nbproc = popcount(curproxy->bind_proc);
6214
6215 curproxy->bind_proc &= nbits(global.nbproc);
6216 if (!curproxy->bind_proc && nbproc == 1) {
6217 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);
6218 curproxy->bind_proc = 1;
6219 }
6220 else if (!curproxy->bind_proc && nbproc > 1) {
6221 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);
6222 curproxy->bind_proc = 0;
6223 }
6224 }
6225
Willy Tarreau3d209582014-05-09 17:06:11 +02006226 /* check and reduce the bind-proc of each listener */
6227 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6228 unsigned long mask;
6229
6230 if (!bind_conf->bind_proc)
6231 continue;
6232
6233 mask = nbits(global.nbproc);
6234 if (curproxy->bind_proc)
6235 mask &= curproxy->bind_proc;
6236 /* mask cannot be null here thanks to the previous checks */
6237
6238 nbproc = popcount(bind_conf->bind_proc);
6239 bind_conf->bind_proc &= mask;
6240
6241 if (!bind_conf->bind_proc && nbproc == 1) {
6242 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",
6243 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6244 bind_conf->bind_proc = mask & ~(mask - 1);
6245 }
6246 else if (!bind_conf->bind_proc && nbproc > 1) {
6247 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",
6248 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6249 bind_conf->bind_proc = 0;
6250 }
6251 }
6252
Willy Tarreau102df612014-05-07 23:56:38 +02006253 if (global.nbproc > 1 && curproxy->table.peers.name) {
6254 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6255 curproxy->id);
6256 cfgerr++;
6257 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006258
Willy Tarreauff01a212009-03-15 13:46:16 +01006259 switch (curproxy->mode) {
6260 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006261 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006262 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006263 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6264 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006265 cfgerr++;
6266 }
6267
6268 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006269 Warning("config : servers will be ignored for %s '%s'.\n",
6270 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006271 break;
6272
6273 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006274 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006275 break;
6276
6277 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006278 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006279 break;
6280 }
6281
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006282 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006283 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006284 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006285 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6286 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006287 cfgerr++;
6288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006289#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006290 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006291 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6292 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006293 cfgerr++;
6294 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006295#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006296 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006297 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6298 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006299 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006300 }
6301 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006302 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006303 /* If no LB algo is set in a backend, and we're not in
6304 * transparent mode, dispatch mode nor proxy mode, we
6305 * want to use balance roundrobin by default.
6306 */
6307 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6308 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006309 }
6310 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006311
Willy Tarreau1620ec32011-08-06 17:05:02 +02006312 if (curproxy->options & PR_O_DISPATCH)
6313 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6314 else if (curproxy->options & PR_O_HTTP_PROXY)
6315 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6316 else if (curproxy->options & PR_O_TRANSP)
6317 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006318
Willy Tarreau1620ec32011-08-06 17:05:02 +02006319 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6320 if (curproxy->options & PR_O_DISABLE404) {
6321 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6322 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6323 err_code |= ERR_WARN;
6324 curproxy->options &= ~PR_O_DISABLE404;
6325 }
6326 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6327 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6328 "send-state", proxy_type_str(curproxy), curproxy->id);
6329 err_code |= ERR_WARN;
6330 curproxy->options &= ~PR_O2_CHK_SNDST;
6331 }
Willy Tarreauef781042010-01-27 11:53:01 +01006332 }
6333
Simon Horman98637e52014-06-20 12:30:16 +09006334 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6335 if (!global.external_check) {
6336 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6337 curproxy->id, "option external-check");
6338 cfgerr++;
6339 }
6340 if (!curproxy->check_command) {
6341 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6342 curproxy->id, "option external-check");
6343 cfgerr++;
6344 }
6345 }
6346
6347 if (curproxy->check_command) {
6348 int clear = 0;
6349 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6350 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6351 "external-check command", proxy_type_str(curproxy), curproxy->id);
6352 err_code |= ERR_WARN;
6353 clear = 1;
6354 }
6355 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6356 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6357 curproxy->id, "external-check command");
6358 cfgerr++;
6359 }
6360 if (clear) {
6361 free(curproxy->check_command);
6362 curproxy->check_command = NULL;
6363 }
6364 }
6365
6366 if (curproxy->check_path) {
6367 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6368 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6369 "external-check path", proxy_type_str(curproxy), curproxy->id);
6370 err_code |= ERR_WARN;
6371 free(curproxy->check_path);
6372 curproxy->check_path = NULL;
6373 }
6374 }
6375
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006376 /* if a default backend was specified, let's find it */
6377 if (curproxy->defbe.name) {
6378 struct proxy *target;
6379
Alex Williams96532db2009-11-01 21:27:13 -05006380 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006381 if (!target) {
6382 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6383 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006384 cfgerr++;
6385 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006386 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6387 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006388 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006389 } else {
6390 free(curproxy->defbe.name);
6391 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006392
6393 /* Emit a warning if this proxy also has some servers */
6394 if (curproxy->srv) {
6395 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6396 curproxy->id);
6397 err_code |= ERR_WARN;
6398 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006399 }
6400 }
6401
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006402 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006403 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6404 /* map jump target for ACT_SETBE in req_rep chain */
6405 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006406 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006407 struct proxy *target;
6408
Willy Tarreaua496b602006-12-17 23:15:24 +01006409 if (exp->action != ACT_SETBE)
6410 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006411
Alex Williams96532db2009-11-01 21:27:13 -05006412 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006413 if (!target) {
6414 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6415 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006416 cfgerr++;
6417 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006418 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6419 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006420 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006421 } else {
6422 free((void *)exp->replace);
6423 exp->replace = (const char *)target;
6424 }
6425 }
6426 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006427
6428 /* find the target proxy for 'use_backend' rules */
6429 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006430 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006431 struct logformat_node *node;
6432 char *pxname;
6433
6434 /* Try to parse the string as a log format expression. If the result
6435 * of the parsing is only one entry containing a simple string, then
6436 * it's a standard string corresponding to a static rule, thus the
6437 * parsing is cancelled and be.name is restored to be resolved.
6438 */
6439 pxname = rule->be.name;
6440 LIST_INIT(&rule->be.expr);
6441 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6442 curproxy->conf.args.file, curproxy->conf.args.line);
6443 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6444
6445 if (!LIST_ISEMPTY(&rule->be.expr)) {
6446 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6447 rule->dynamic = 1;
6448 free(pxname);
6449 continue;
6450 }
6451 /* simple string: free the expression and fall back to static rule */
6452 free(node->arg);
6453 free(node);
6454 }
6455
6456 rule->dynamic = 0;
6457 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006458
Alex Williams96532db2009-11-01 21:27:13 -05006459 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006460
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006461 if (!target) {
6462 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6463 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006464 cfgerr++;
6465 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006466 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6467 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006468 cfgerr++;
6469 } else {
6470 free((void *)rule->be.name);
6471 rule->be.backend = target;
6472 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006473 }
6474
Willy Tarreau64ab6072014-09-16 12:17:36 +02006475 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006476 list_for_each_entry(srule, &curproxy->server_rules, list) {
6477 struct server *target = findserver(curproxy, srule->srv.name);
6478
6479 if (!target) {
6480 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6481 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6482 cfgerr++;
6483 continue;
6484 }
6485 free((void *)srule->srv.name);
6486 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006487 }
6488
Emeric Brunb982a3d2010-01-04 15:45:53 +01006489 /* find the target table for 'stick' rules */
6490 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6491 struct proxy *target;
6492
Emeric Brun1d33b292010-01-04 15:47:17 +01006493 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6494 if (mrule->flags & STK_IS_STORE)
6495 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6496
Emeric Brunb982a3d2010-01-04 15:45:53 +01006497 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006498 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006499 else
6500 target = curproxy;
6501
6502 if (!target) {
6503 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6504 curproxy->id, mrule->table.name);
6505 cfgerr++;
6506 }
6507 else if (target->table.size == 0) {
6508 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6509 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6510 cfgerr++;
6511 }
Willy Tarreau12785782012-04-27 21:37:17 +02006512 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6513 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006514 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6515 cfgerr++;
6516 }
6517 else {
6518 free((void *)mrule->table.name);
6519 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006520 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006521 }
6522 }
6523
6524 /* find the target table for 'store response' rules */
6525 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6526 struct proxy *target;
6527
Emeric Brun1d33b292010-01-04 15:47:17 +01006528 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6529
Emeric Brunb982a3d2010-01-04 15:45:53 +01006530 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006531 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006532 else
6533 target = curproxy;
6534
6535 if (!target) {
6536 Alert("Proxy '%s': unable to find store table '%s'.\n",
6537 curproxy->id, mrule->table.name);
6538 cfgerr++;
6539 }
6540 else if (target->table.size == 0) {
6541 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6542 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6543 cfgerr++;
6544 }
Willy Tarreau12785782012-04-27 21:37:17 +02006545 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6546 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006547 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6548 cfgerr++;
6549 }
6550 else {
6551 free((void *)mrule->table.name);
6552 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006553 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006554 }
6555 }
6556
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006557 /* find the target table for 'tcp-request' layer 4 rules */
6558 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6559 struct proxy *target;
6560
Willy Tarreaub4c84932013-07-23 19:15:30 +02006561 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006562 continue;
6563
6564 if (trule->act_prm.trk_ctr.table.n)
6565 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6566 else
6567 target = curproxy;
6568
6569 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006570 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6571 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006572 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006573 cfgerr++;
6574 }
6575 else if (target->table.size == 0) {
6576 Alert("Proxy '%s': table '%s' used but not configured.\n",
6577 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6578 cfgerr++;
6579 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006580 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6581 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6582 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 +01006583 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006584 cfgerr++;
6585 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006586 else {
6587 free(trule->act_prm.trk_ctr.table.n);
6588 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006589 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006590 * to pass a list of counters to track and allocate them right here using
6591 * stktable_alloc_data_type().
6592 */
6593 }
6594 }
6595
Willy Tarreaud1f96522010-08-03 19:34:32 +02006596 /* find the target table for 'tcp-request' layer 6 rules */
6597 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6598 struct proxy *target;
6599
Willy Tarreaub4c84932013-07-23 19:15:30 +02006600 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006601 continue;
6602
6603 if (trule->act_prm.trk_ctr.table.n)
6604 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6605 else
6606 target = curproxy;
6607
6608 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006609 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6610 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006611 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006612 cfgerr++;
6613 }
6614 else if (target->table.size == 0) {
6615 Alert("Proxy '%s': table '%s' used but not configured.\n",
6616 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6617 cfgerr++;
6618 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006619 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6620 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6621 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 +01006622 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006623 cfgerr++;
6624 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006625 else {
6626 free(trule->act_prm.trk_ctr.table.n);
6627 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006628 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006629 * to pass a list of counters to track and allocate them right here using
6630 * stktable_alloc_data_type().
6631 */
6632 }
6633 }
6634
Willy Tarreau09448f72014-06-25 18:12:15 +02006635 /* find the target table for 'http-request' layer 7 rules */
6636 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6637 struct proxy *target;
6638
6639 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6640 continue;
6641
6642 if (hrqrule->act_prm.trk_ctr.table.n)
6643 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6644 else
6645 target = curproxy;
6646
6647 if (!target) {
6648 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6649 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6650 http_req_trk_idx(hrqrule->action));
6651 cfgerr++;
6652 }
6653 else if (target->table.size == 0) {
6654 Alert("Proxy '%s': table '%s' used but not configured.\n",
6655 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6656 cfgerr++;
6657 }
6658 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6659 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6660 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6661 http_req_trk_idx(hrqrule->action));
6662 cfgerr++;
6663 }
6664 else {
6665 free(hrqrule->act_prm.trk_ctr.table.n);
6666 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6667 /* Note: if we decide to enhance the track-sc syntax, we may be able
6668 * to pass a list of counters to track and allocate them right here using
6669 * stktable_alloc_data_type().
6670 */
6671 }
6672 }
6673
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006674 /* move any "block" rules at the beginning of the http-request rules */
6675 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6676 /* insert block_rules into http_req_rules at the beginning */
6677 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6678 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6679 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6680 curproxy->http_req_rules.n = curproxy->block_rules.n;
6681 LIST_INIT(&curproxy->block_rules);
6682 }
6683
Emeric Brun32da3c42010-09-23 18:39:19 +02006684 if (curproxy->table.peers.name) {
6685 struct peers *curpeers = peers;
6686
6687 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6688 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6689 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006690 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006691 break;
6692 }
6693 }
6694
6695 if (!curpeers) {
6696 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6697 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006698 free((void *)curproxy->table.peers.name);
6699 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006700 cfgerr++;
6701 }
6702 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006703 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6704 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006705 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006706 cfgerr++;
6707 }
6708 }
6709
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006710 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006711 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006712 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6713 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6714 "proxy", curproxy->id);
6715 cfgerr++;
6716 goto out_uri_auth_compat;
6717 }
6718
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006719 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006720 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006721 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006722 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006723
Willy Tarreau95fa4692010-02-01 13:05:50 +01006724 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6725 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006726
6727 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006728 uri_auth_compat_req[i++] = "realm";
6729 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6730 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006731
Willy Tarreau95fa4692010-02-01 13:05:50 +01006732 uri_auth_compat_req[i++] = "unless";
6733 uri_auth_compat_req[i++] = "{";
6734 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6735 uri_auth_compat_req[i++] = "}";
6736 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006737
Willy Tarreauff011f22011-01-06 17:51:27 +01006738 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6739 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006740 cfgerr++;
6741 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006742 }
6743
Willy Tarreauff011f22011-01-06 17:51:27 +01006744 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006745
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006746 if (curproxy->uri_auth->auth_realm) {
6747 free(curproxy->uri_auth->auth_realm);
6748 curproxy->uri_auth->auth_realm = NULL;
6749 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006750
6751 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006752 }
6753out_uri_auth_compat:
6754
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006755 /* compile the log format */
6756 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006757 if (curproxy->conf.logformat_string != default_http_log_format &&
6758 curproxy->conf.logformat_string != default_tcp_log_format &&
6759 curproxy->conf.logformat_string != clf_http_log_format)
6760 free(curproxy->conf.logformat_string);
6761 curproxy->conf.logformat_string = NULL;
6762 free(curproxy->conf.lfs_file);
6763 curproxy->conf.lfs_file = NULL;
6764 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006765 }
6766
Willy Tarreau62a61232013-04-12 18:13:46 +02006767 if (curproxy->conf.logformat_string) {
6768 curproxy->conf.args.ctx = ARGC_LOG;
6769 curproxy->conf.args.file = curproxy->conf.lfs_file;
6770 curproxy->conf.args.line = curproxy->conf.lfs_line;
6771 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006772 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006773 curproxy->conf.args.file = NULL;
6774 curproxy->conf.args.line = 0;
6775 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006776
Willy Tarreau62a61232013-04-12 18:13:46 +02006777 if (curproxy->conf.uniqueid_format_string) {
6778 curproxy->conf.args.ctx = ARGC_UIF;
6779 curproxy->conf.args.file = curproxy->conf.uif_file;
6780 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006781 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08006782 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006783 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006784 curproxy->conf.args.file = NULL;
6785 curproxy->conf.args.line = 0;
6786 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006787
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006788 /* only now we can check if some args remain unresolved.
6789 * This must be done after the users and groups resolution.
6790 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006791 cfgerr += smp_resolve_args(curproxy);
6792 if (!cfgerr)
6793 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006794
Willy Tarreau2738a142006-07-08 17:28:09 +02006795 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006796 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006797 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006798 (!curproxy->timeout.connect ||
6799 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006800 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006801 " | While not properly invalid, you will certainly encounter various problems\n"
6802 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006803 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006804 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006805 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006806 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006807
Willy Tarreau1fa31262007-12-03 00:36:16 +01006808 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6809 * We must still support older configurations, so let's find out whether those
6810 * parameters have been set or must be copied from contimeouts.
6811 */
6812 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006813 if (!curproxy->timeout.tarpit ||
6814 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006815 /* tarpit timeout not set. We search in the following order:
6816 * default.tarpit, curr.connect, default.connect.
6817 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006818 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006819 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006820 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006821 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006822 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006823 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006824 }
6825 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006826 (!curproxy->timeout.queue ||
6827 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006828 /* queue timeout not set. We search in the following order:
6829 * default.queue, curr.connect, default.connect.
6830 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006831 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006832 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006833 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006834 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006835 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006836 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006837 }
6838 }
6839
Willy Tarreau1620ec32011-08-06 17:05:02 +02006840 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006841 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6842 curproxy->check_req = (char *)malloc(curproxy->check_len);
6843 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006844 }
6845
Willy Tarreau215663d2014-06-13 18:30:23 +02006846 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6847 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6848 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6849 proxy_type_str(curproxy), curproxy->id);
6850 err_code |= ERR_WARN;
6851 }
6852
Willy Tarreau193b8c62012-11-22 00:17:38 +01006853 /* ensure that cookie capture length is not too large */
6854 if (curproxy->capture_len >= global.tune.cookie_len) {
6855 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6856 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6857 err_code |= ERR_WARN;
6858 curproxy->capture_len = global.tune.cookie_len - 1;
6859 }
6860
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006861 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006862 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006863 curproxy->req_cap_pool = create_pool("ptrcap",
6864 curproxy->nb_req_cap * sizeof(char *),
6865 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006866 }
6867
6868 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006869 curproxy->rsp_cap_pool = create_pool("ptrcap",
6870 curproxy->nb_rsp_cap * sizeof(char *),
6871 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006872 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006873
Willy Tarreaubaaee002006-06-26 02:48:02 +02006874 /* first, we will invert the servers list order */
6875 newsrv = NULL;
6876 while (curproxy->srv) {
6877 struct server *next;
6878
6879 next = curproxy->srv->next;
6880 curproxy->srv->next = newsrv;
6881 newsrv = curproxy->srv;
6882 if (!next)
6883 break;
6884 curproxy->srv = next;
6885 }
6886
Willy Tarreau17edc812014-01-03 12:14:34 +01006887 /* Check that no server name conflicts. This causes trouble in the stats.
6888 * We only emit a warning for the first conflict affecting each server,
6889 * in order to avoid combinatory explosion if all servers have the same
6890 * name. We do that only for servers which do not have an explicit ID,
6891 * because these IDs were made also for distinguishing them and we don't
6892 * want to annoy people who correctly manage them.
6893 */
6894 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6895 struct server *other_srv;
6896
6897 if (newsrv->puid)
6898 continue;
6899
6900 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6901 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6902 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6903 newsrv->conf.file, newsrv->conf.line,
6904 proxy_type_str(curproxy), curproxy->id,
6905 newsrv->id, other_srv->conf.line);
6906 break;
6907 }
6908 }
6909 }
6910
Willy Tarreaudd701652010-05-25 23:03:02 +02006911 /* assign automatic UIDs to servers which don't have one yet */
6912 next_id = 1;
6913 newsrv = curproxy->srv;
6914 while (newsrv != NULL) {
6915 if (!newsrv->puid) {
6916 /* server ID not set, use automatic numbering with first
6917 * spare entry starting with next_svid.
6918 */
6919 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6920 newsrv->conf.id.key = newsrv->puid = next_id;
6921 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6922 }
6923 next_id++;
6924 newsrv = newsrv->next;
6925 }
6926
Willy Tarreau20697042007-11-15 23:26:18 +01006927 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006928 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006929
Willy Tarreau62c3be22012-01-20 13:12:32 +01006930 /*
6931 * If this server supports a maxconn parameter, it needs a dedicated
6932 * tasks to fill the emptied slots when a connection leaves.
6933 * Also, resolve deferred tracking dependency if needed.
6934 */
6935 newsrv = curproxy->srv;
6936 while (newsrv != NULL) {
6937 if (newsrv->minconn > newsrv->maxconn) {
6938 /* Only 'minconn' was specified, or it was higher than or equal
6939 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6940 * this will avoid further useless expensive computations.
6941 */
6942 newsrv->maxconn = newsrv->minconn;
6943 } else if (newsrv->maxconn && !newsrv->minconn) {
6944 /* minconn was not specified, so we set it to maxconn */
6945 newsrv->minconn = newsrv->maxconn;
6946 }
6947
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006948#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006949 if (newsrv->use_ssl || newsrv->check.use_ssl)
6950 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006951#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006952
Willy Tarreau2f075e92013-12-03 11:11:34 +01006953 /* set the check type on the server */
6954 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6955
Willy Tarreau62c3be22012-01-20 13:12:32 +01006956 if (newsrv->trackit) {
6957 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006958 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006959 char *pname, *sname;
6960
6961 pname = newsrv->trackit;
6962 sname = strrchr(pname, '/');
6963
6964 if (sname)
6965 *sname++ = '\0';
6966 else {
6967 sname = pname;
6968 pname = NULL;
6969 }
6970
6971 if (pname) {
6972 px = findproxy(pname, PR_CAP_BE);
6973 if (!px) {
6974 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6975 proxy_type_str(curproxy), curproxy->id,
6976 newsrv->id, pname);
6977 cfgerr++;
6978 goto next_srv;
6979 }
6980 } else
6981 px = curproxy;
6982
6983 srv = findserver(px, sname);
6984 if (!srv) {
6985 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6986 proxy_type_str(curproxy), curproxy->id,
6987 newsrv->id, sname);
6988 cfgerr++;
6989 goto next_srv;
6990 }
6991
Willy Tarreau32091232014-05-16 13:52:00 +02006992 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6993 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6994 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006995 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006996 "tracking as it does not have any check nor agent enabled.\n",
6997 proxy_type_str(curproxy), curproxy->id,
6998 newsrv->id, px->id, srv->id);
6999 cfgerr++;
7000 goto next_srv;
7001 }
7002
7003 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7004
7005 if (loop) {
7006 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7007 "belongs to a tracking chain looping back to %s/%s.\n",
7008 proxy_type_str(curproxy), curproxy->id,
7009 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007010 cfgerr++;
7011 goto next_srv;
7012 }
7013
7014 if (curproxy != px &&
7015 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7016 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7017 "tracking: disable-on-404 option inconsistency.\n",
7018 proxy_type_str(curproxy), curproxy->id,
7019 newsrv->id, px->id, srv->id);
7020 cfgerr++;
7021 goto next_srv;
7022 }
7023
7024 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007025 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007026 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007027 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007028 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09007029 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007030 }
7031
7032 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007033 newsrv->tracknext = srv->trackers;
7034 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007035
7036 free(newsrv->trackit);
7037 newsrv->trackit = NULL;
7038 }
7039 next_srv:
7040 newsrv = newsrv->next;
7041 }
7042
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007043 /* We have to initialize the server lookup mechanism depending
7044 * on what LB algorithm was choosen.
7045 */
7046
7047 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7048 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7049 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007050 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7051 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7052 init_server_map(curproxy);
7053 } else {
7054 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7055 fwrr_init_server_groups(curproxy);
7056 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007057 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007058
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007059 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007060 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7061 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7062 fwlc_init_server_tree(curproxy);
7063 } else {
7064 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7065 fas_init_server_tree(curproxy);
7066 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007067 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007068
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007069 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007070 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7071 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7072 chash_init_server_tree(curproxy);
7073 } else {
7074 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7075 init_server_map(curproxy);
7076 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007077 break;
7078 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007079
7080 if (curproxy->options & PR_O_LOGASAP)
7081 curproxy->to_log &= ~LW_BYTES;
7082
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007083 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007084 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007085 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7086 proxy_type_str(curproxy), curproxy->id);
7087 err_code |= ERR_WARN;
7088 }
7089
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007090 if (curproxy->mode != PR_MODE_HTTP) {
7091 int optnum;
7092
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007093 if (curproxy->uri_auth) {
7094 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7095 proxy_type_str(curproxy), curproxy->id);
7096 err_code |= ERR_WARN;
7097 curproxy->uri_auth = NULL;
7098 }
7099
Willy Tarreau87cf5142011-08-19 22:57:24 +02007100 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007101 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7102 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7103 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007104 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007105 }
7106
7107 if (curproxy->options & PR_O_ORGTO) {
7108 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7109 "originalto", proxy_type_str(curproxy), curproxy->id);
7110 err_code |= ERR_WARN;
7111 curproxy->options &= ~PR_O_ORGTO;
7112 }
7113
7114 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7115 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7116 (curproxy->cap & cfg_opts[optnum].cap) &&
7117 (curproxy->options & cfg_opts[optnum].val)) {
7118 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7119 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7120 err_code |= ERR_WARN;
7121 curproxy->options &= ~cfg_opts[optnum].val;
7122 }
7123 }
7124
7125 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7126 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7127 (curproxy->cap & cfg_opts2[optnum].cap) &&
7128 (curproxy->options2 & cfg_opts2[optnum].val)) {
7129 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7130 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7131 err_code |= ERR_WARN;
7132 curproxy->options2 &= ~cfg_opts2[optnum].val;
7133 }
7134 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007135
Pieter Baauwd551fb52013-05-08 22:49:23 +02007136#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007137 if (curproxy->conn_src.bind_hdr_occ) {
7138 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007139 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007140 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007141 err_code |= ERR_WARN;
7142 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007143#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007144 }
7145
Willy Tarreaubaaee002006-06-26 02:48:02 +02007146 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007147 * ensure that we're not cross-dressing a TCP server into HTTP.
7148 */
7149 newsrv = curproxy->srv;
7150 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007151 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007152 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7153 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007154 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007155 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007156
Willy Tarreau0cec3312011-10-31 13:49:26 +01007157 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7158 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7159 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7160 err_code |= ERR_WARN;
7161 }
7162
Willy Tarreauc93cd162014-05-13 15:54:22 +02007163 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007164 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7165 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7166 err_code |= ERR_WARN;
7167 }
7168
Pieter Baauwd551fb52013-05-08 22:49:23 +02007169#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007170 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7171 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007172 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 +01007173 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007174 err_code |= ERR_WARN;
7175 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007176#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007177 newsrv = newsrv->next;
7178 }
7179
Willy Tarreaue42bd962014-09-16 16:21:19 +02007180 /* check if we have a frontend with "tcp-request content" looking at L7
7181 * with no inspect-delay
7182 */
7183 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7184 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7185 if (trule->action == TCP_ACT_CAPTURE &&
7186 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7187 break;
7188 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7189 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7190 break;
7191 }
7192
7193 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7194 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7195 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7196 " This means that these rules will randomly find their contents. This can be fixed by"
7197 " setting the tcp-request inspect-delay.\n",
7198 proxy_type_str(curproxy), curproxy->id);
7199 err_code |= ERR_WARN;
7200 }
7201 }
7202
Willy Tarreauc1a21672009-08-16 22:37:44 +02007203 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007204 if (!curproxy->accept)
7205 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007206
Willy Tarreauc1a21672009-08-16 22:37:44 +02007207 if (curproxy->tcp_req.inspect_delay ||
7208 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007209 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007210
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007211 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007212 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007213 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007214 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007215
7216 /* both TCP and HTTP must check switching rules */
7217 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7218 }
7219
7220 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007221 if (curproxy->tcp_req.inspect_delay ||
7222 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7223 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7224
Emeric Brun97679e72010-09-23 17:56:44 +02007225 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7226 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7227
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007228 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007229 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007230 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007231 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007232
7233 /* If the backend does requires RDP cookie persistence, we have to
7234 * enable the corresponding analyser.
7235 */
7236 if (curproxy->options2 & PR_O2_RDPC_PRST)
7237 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7238 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007239 }
7240
7241 /***********************************************************/
7242 /* At this point, target names have already been resolved. */
7243 /***********************************************************/
7244
7245 /* Check multi-process mode compatibility */
7246
7247 if (global.nbproc > 1 && global.stats_fe) {
7248 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7249 unsigned long mask;
7250
7251 mask = nbits(global.nbproc);
7252 if (global.stats_fe->bind_proc)
7253 mask &= global.stats_fe->bind_proc;
7254
7255 if (bind_conf->bind_proc)
7256 mask &= bind_conf->bind_proc;
7257
7258 /* stop here if more than one process is used */
7259 if (popcount(mask) > 1)
7260 break;
7261 }
7262 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7263 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");
7264 }
7265 }
7266
7267 /* Make each frontend inherit bind-process from its listeners when not specified. */
7268 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7269 if (curproxy->bind_proc)
7270 continue;
7271
7272 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7273 unsigned long mask;
7274
7275 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7276 curproxy->bind_proc |= mask;
7277 }
7278
7279 if (!curproxy->bind_proc)
7280 curproxy->bind_proc = ~0UL;
7281 }
7282
7283 if (global.stats_fe) {
7284 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7285 unsigned long mask;
7286
7287 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7288 global.stats_fe->bind_proc |= mask;
7289 }
7290 if (!global.stats_fe->bind_proc)
7291 global.stats_fe->bind_proc = ~0UL;
7292 }
7293
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007294 /* propagate bindings from frontends to backends. Don't do it if there
7295 * are any fatal errors as we must not call it with unresolved proxies.
7296 */
7297 if (!cfgerr) {
7298 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7299 if (curproxy->cap & PR_CAP_FE)
7300 propagate_processes(curproxy, NULL);
7301 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007302 }
7303
7304 /* Bind each unbound backend to all processes when not specified. */
7305 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7306 if (curproxy->bind_proc)
7307 continue;
7308 curproxy->bind_proc = ~0UL;
7309 }
7310
7311 /*******************************************************/
7312 /* At this step, all proxies have a non-null bind_proc */
7313 /*******************************************************/
7314
7315 /* perform the final checks before creating tasks */
7316
7317 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7318 struct listener *listener;
7319 unsigned int next_id;
7320 int nbproc;
7321
7322 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007323
Emeric Brunc52962f2012-11-15 18:28:02 +01007324#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007325 /* Configure SSL for each bind line.
7326 * Note: if configuration fails at some point, the ->ctx member
7327 * remains NULL so that listeners can later detach.
7328 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007329 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007330 int alloc_ctx;
7331
Emeric Brunc52962f2012-11-15 18:28:02 +01007332 if (!bind_conf->is_ssl) {
7333 if (bind_conf->default_ctx) {
7334 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7335 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7336 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007337 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007338 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007339 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007340 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007341 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007342 cfgerr++;
7343 continue;
7344 }
7345
Emeric Brun8dc60392014-05-09 13:52:00 +02007346 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007347 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007348 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7349 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");
7350 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007351 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007352 cfgerr++;
7353 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007354 }
7355
Emeric Brunfc0421f2012-09-07 17:30:07 +02007356 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007357 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007358 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007359#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007360
Willy Tarreaue6b98942007-10-29 01:09:36 +01007361 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007362 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007363 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007364 if (!listener->luid) {
7365 /* listener ID not set, use automatic numbering with first
7366 * spare entry starting with next_luid.
7367 */
7368 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7369 listener->conf.id.key = listener->luid = next_id;
7370 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007371 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007372 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007373
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007374 /* enable separate counters */
7375 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7376 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007377 if (!listener->name)
7378 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007379 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007380
Willy Tarreaue6b98942007-10-29 01:09:36 +01007381 if (curproxy->options & PR_O_TCP_NOLING)
7382 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007383 if (!listener->maxconn)
7384 listener->maxconn = curproxy->maxconn;
7385 if (!listener->backlog)
7386 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007387 if (!listener->maxaccept)
7388 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7389
7390 /* we want to have an optimal behaviour on single process mode to
7391 * maximize the work at once, but in multi-process we want to keep
7392 * some fairness between processes, so we target half of the max
7393 * number of events to be balanced over all the processes the proxy
7394 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7395 * used to disable the limit.
7396 */
7397 if (listener->maxaccept > 0) {
7398 if (nbproc > 1)
7399 listener->maxaccept = (listener->maxaccept + 1) / 2;
7400 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7401 }
7402
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007403 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007404 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007405 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007406 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007407
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007408 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7409 listener->options |= LI_O_TCP_RULES;
7410
Willy Tarreaude3041d2010-05-31 10:56:17 +02007411 if (curproxy->mon_mask.s_addr)
7412 listener->options |= LI_O_CHK_MONNET;
7413
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007414 /* smart accept mode is automatic in HTTP mode */
7415 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007416 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007417 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7418 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007419 }
7420
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007421 /* Release unused SSL configs */
7422 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7423 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007424 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007425#ifdef USE_OPENSSL
7426 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007427 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007428 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007429 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007430 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007431#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007432 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007433
Willy Tarreau102df612014-05-07 23:56:38 +02007434 if (nbproc > 1) {
7435 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02007436 int count, maxproc = 0;
7437
7438 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7439 count = popcount(bind_conf->bind_proc);
7440 if (count > maxproc)
7441 maxproc = count;
7442 }
7443 /* backends have 0, frontends have 1 or more */
7444 if (maxproc != 1)
7445 Warning("Proxy '%s': in multi-process mode, stats will be"
7446 " limited to process assigned to the current request.\n",
7447 curproxy->id);
7448
Willy Tarreau102df612014-05-07 23:56:38 +02007449 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7450 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7451 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007452 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007453 }
Willy Tarreau102df612014-05-07 23:56:38 +02007454 if (curproxy->appsession_name) {
7455 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7456 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007457 }
Willy Tarreau102df612014-05-07 23:56:38 +02007458 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7459 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7460 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007461 }
7462 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007463
7464 /* create the task associated with the proxy */
7465 curproxy->task = task_new();
7466 if (curproxy->task) {
7467 curproxy->task->context = curproxy;
7468 curproxy->task->process = manage_proxy;
7469 /* no need to queue, it will be done automatically if some
7470 * listener gets limited.
7471 */
7472 curproxy->task->expire = TICK_ETERNITY;
7473 } else {
7474 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7475 curproxy->id);
7476 cfgerr++;
7477 }
Willy Tarreaub369a042014-09-16 13:21:03 +02007478 }
7479
Willy Tarreaufbb78422011-06-05 15:38:35 +02007480 /* automatically compute fullconn if not set. We must not do it in the
7481 * loop above because cross-references are not yet fully resolved.
7482 */
7483 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7484 /* If <fullconn> is not set, let's set it to 10% of the sum of
7485 * the possible incoming frontend's maxconns.
7486 */
7487 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7488 struct proxy *fe;
7489 int total = 0;
7490
7491 /* sum up the number of maxconns of frontends which
7492 * reference this backend at least once or which are
7493 * the same one ('listen').
7494 */
7495 for (fe = proxy; fe; fe = fe->next) {
7496 struct switching_rule *rule;
7497 struct hdr_exp *exp;
7498 int found = 0;
7499
7500 if (!(fe->cap & PR_CAP_FE))
7501 continue;
7502
7503 if (fe == curproxy) /* we're on a "listen" instance */
7504 found = 1;
7505
7506 if (fe->defbe.be == curproxy) /* "default_backend" */
7507 found = 1;
7508
7509 /* check if a "use_backend" rule matches */
7510 if (!found) {
7511 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007512 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007513 found = 1;
7514 break;
7515 }
7516 }
7517 }
7518
7519 /* check if a "reqsetbe" rule matches */
7520 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7521 if (exp->action == ACT_SETBE &&
7522 (struct proxy *)exp->replace == curproxy) {
7523 found = 1;
7524 break;
7525 }
7526 }
7527
7528 /* now we've checked all possible ways to reference a backend
7529 * from a frontend.
7530 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007531 if (!found)
7532 continue;
7533 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007534 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007535 /* we have the sum of the maxconns in <total>. We only
7536 * keep 10% of that sum to set the default fullconn, with
7537 * a hard minimum of 1 (to avoid a divide by zero).
7538 */
7539 curproxy->fullconn = (total + 9) / 10;
7540 if (!curproxy->fullconn)
7541 curproxy->fullconn = 1;
7542 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007543 }
7544
Willy Tarreau056f5682010-06-06 15:51:11 +02007545 /* initialize stick-tables on backend capable proxies. This must not
7546 * be done earlier because the data size may be discovered while parsing
7547 * other proxies.
7548 */
Godbach9703e662013-12-11 21:11:41 +08007549 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007550 if (curproxy->state == PR_STSTOPPED)
7551 continue;
7552
Godbach9703e662013-12-11 21:11:41 +08007553 if (!stktable_init(&curproxy->table)) {
7554 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7555 cfgerr++;
7556 }
7557 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007558
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007559 /*
7560 * Recount currently required checks.
7561 */
7562
7563 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7564 int optnum;
7565
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007566 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7567 if (curproxy->options & cfg_opts[optnum].val)
7568 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007569
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007570 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7571 if (curproxy->options2 & cfg_opts2[optnum].val)
7572 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007573 }
7574
Willy Tarreau122541c2011-09-07 21:24:49 +02007575 if (peers) {
7576 struct peers *curpeers = peers, **last;
7577 struct peer *p, *pb;
7578
7579 /* Remove all peers sections which don't have a valid listener.
7580 * This can happen when a peers section is never referenced and
7581 * does not contain a local peer.
7582 */
7583 last = &peers;
7584 while (*last) {
7585 curpeers = *last;
7586 if (curpeers->peers_fe) {
7587 last = &curpeers->next;
7588 continue;
7589 }
7590
7591 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7592 curpeers->id, localpeer);
7593
7594 p = curpeers->remote;
7595 while (p) {
7596 pb = p->next;
7597 free(p->id);
7598 free(p);
7599 p = pb;
7600 }
7601
7602 /* Destroy and unlink this curpeers section.
7603 * Note: curpeers is backed up into *last.
7604 */
7605 free(curpeers->id);
7606 curpeers = curpeers->next;
7607 free(*last);
7608 *last = curpeers;
7609 }
7610 }
7611
Willy Tarreau34eb6712011-10-24 18:15:04 +02007612 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007613 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007614 MEM_F_SHARED);
7615
Willy Tarreaubb925012009-07-23 13:36:36 +02007616 if (cfgerr > 0)
7617 err_code |= ERR_ALERT | ERR_FATAL;
7618 out:
7619 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007620}
7621
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007622/*
7623 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7624 * parsing sessions.
7625 */
7626void cfg_register_keywords(struct cfg_kw_list *kwl)
7627{
7628 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7629}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007630
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007631/*
7632 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7633 */
7634void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7635{
7636 LIST_DEL(&kwl->list);
7637 LIST_INIT(&kwl->list);
7638}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007639
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007640/* this function register new section in the haproxy configuration file.
7641 * <section_name> is the name of this new section and <section_parser>
7642 * is the called parser. If two section declaration have the same name,
7643 * only the first declared is used.
7644 */
7645int cfg_register_section(char *section_name,
7646 int (*section_parser)(const char *, int, char **, int))
7647{
7648 struct cfg_section *cs;
7649
7650 cs = calloc(1, sizeof(*cs));
7651 if (!cs) {
7652 Alert("register section '%s': out of memory.\n", section_name);
7653 return 0;
7654 }
7655
7656 cs->section_name = section_name;
7657 cs->section_parser = section_parser;
7658
7659 LIST_ADDQ(&sections, &cs->list);
7660
7661 return 1;
7662}
7663
Willy Tarreaubaaee002006-06-26 02:48:02 +02007664/*
7665 * Local variables:
7666 * c-indent-level: 8
7667 * c-basic-offset: 8
7668 * End:
7669 */