blob: 5cb7ad9247ea71e37f7744ae0beb71bb8474a357 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté2c8d7002014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044
45#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010048#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020049#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050
Willy Tarreaueb0c6142007-05-07 00:53:22 +020051#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010052#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020054#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020056#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020057#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020058#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020059#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020060#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010061#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020062#include <proto/lb_fwlc.h>
63#include <proto/lb_fwrr.h>
64#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020065#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020066#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020067#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010068#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020069#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010070#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010071#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020072#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020073#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020074#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010075#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020076#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020077#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010078#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020079
Emeric Brunfc0421f2012-09-07 17:30:07 +020080#ifdef USE_OPENSSL
81#include <types/ssl_sock.h>
82#include <proto/ssl_sock.h>
83#include <proto/shctx.h>
84#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020085
Willy Tarreauf3c69202006-07-09 16:42:34 +020086/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
87 * ssl-hello-chk option to ensure that the remote server speaks SSL.
88 *
89 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
90 */
91const char sslv3_client_hello_pkt[] = {
92 "\x16" /* ContentType : 0x16 = Hanshake */
93 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
94 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
95 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
96 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
97 "\x03\x00" /* Hello Version : 0x0300 = v3 */
98 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
99 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
100 "\x00" /* Session ID length : empty (no session ID) */
101 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
102 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
103 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
104 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
105 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
106 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
107 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
108 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
109 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
110 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
111 "\x00\x38" "\x00\x39" "\x00\x3A"
112 "\x01" /* Compression Length : 0x01 = 1 byte for types */
113 "\x00" /* Compression Type : 0x00 = NULL compression */
114};
115
Willy Tarreau3842f002009-06-14 11:39:52 +0200116/* various keyword modifiers */
117enum kw_mod {
118 KWM_STD = 0, /* normal */
119 KWM_NO, /* "no" prefixed before the keyword */
120 KWM_DEF, /* "default" prefixed before the keyword */
121};
122
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100123/* permit to store configuration section */
124struct cfg_section {
125 struct list list;
126 char *section_name;
127 int (*section_parser)(const char *, int, char **, int);
128};
129
130/* Used to chain configuration sections definitions. This list
131 * stores struct cfg_section
132 */
133struct list sections = LIST_HEAD_INIT(sections);
134
Willy Tarreau13943ab2006-12-31 00:24:10 +0100135/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100136struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100137 const char *name;
138 unsigned int val;
139 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100140 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100141 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142};
143
144/* proxy->options */
145static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
148 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
149 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
150 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
151 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
152 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau1c3a6122015-05-01 15:37:53 +0200154 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 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 Tarreau8b3c8082014-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 Tarreau8b3c8082014-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]);
Willy Tarreau47c7d632015-09-28 13:49:53 +0200706 if (global.tune.bufsize <= 0) {
707 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
708 err_code |= ERR_ALERT | ERR_FATAL;
709 goto out;
710 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200711 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
712 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100713 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100714 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200715 }
716 else if (!strcmp(args[0], "tune.maxrewrite")) {
717 if (*(args[1]) == 0) {
718 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
721 }
722 global.tune.maxrewrite = atol(args[1]);
723 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
724 global.tune.maxrewrite = global.tune.bufsize / 2;
725 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100726 else if (!strcmp(args[0], "tune.idletimer")) {
727 unsigned int idle;
728 const char *res;
729
730 if (*(args[1]) == 0) {
731 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
734 }
735
736 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
737 if (res) {
738 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
739 file, linenum, *res, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743
744 if (idle > 65535) {
745 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
746 err_code |= ERR_ALERT | ERR_FATAL;
747 goto out;
748 }
749 global.tune.idle_timer = idle;
750 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100751 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
752 if (global.tune.client_rcvbuf != 0) {
753 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
754 err_code |= ERR_ALERT;
755 goto out;
756 }
757 if (*(args[1]) == 0) {
758 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
759 err_code |= ERR_ALERT | ERR_FATAL;
760 goto out;
761 }
762 global.tune.client_rcvbuf = atol(args[1]);
763 }
764 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
765 if (global.tune.server_rcvbuf != 0) {
766 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
767 err_code |= ERR_ALERT;
768 goto out;
769 }
770 if (*(args[1]) == 0) {
771 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
772 err_code |= ERR_ALERT | ERR_FATAL;
773 goto out;
774 }
775 global.tune.server_rcvbuf = atol(args[1]);
776 }
777 else if (!strcmp(args[0], "tune.sndbuf.client")) {
778 if (global.tune.client_sndbuf != 0) {
779 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
780 err_code |= ERR_ALERT;
781 goto out;
782 }
783 if (*(args[1]) == 0) {
784 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
785 err_code |= ERR_ALERT | ERR_FATAL;
786 goto out;
787 }
788 global.tune.client_sndbuf = atol(args[1]);
789 }
790 else if (!strcmp(args[0], "tune.sndbuf.server")) {
791 if (global.tune.server_sndbuf != 0) {
792 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
793 err_code |= ERR_ALERT;
794 goto out;
795 }
796 if (*(args[1]) == 0) {
797 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
798 err_code |= ERR_ALERT | ERR_FATAL;
799 goto out;
800 }
801 global.tune.server_sndbuf = atol(args[1]);
802 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200803 else if (!strcmp(args[0], "tune.pipesize")) {
804 if (*(args[1]) == 0) {
805 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
806 err_code |= ERR_ALERT | ERR_FATAL;
807 goto out;
808 }
809 global.tune.pipesize = atol(args[1]);
810 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100811 else if (!strcmp(args[0], "tune.http.cookielen")) {
812 if (*(args[1]) == 0) {
813 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
814 err_code |= ERR_ALERT | ERR_FATAL;
815 goto out;
816 }
817 global.tune.cookie_len = atol(args[1]) + 1;
818 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200819 else if (!strcmp(args[0], "tune.http.maxhdr")) {
820 if (*(args[1]) == 0) {
821 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
822 err_code |= ERR_ALERT | ERR_FATAL;
823 goto out;
824 }
825 global.tune.max_http_hdr = atol(args[1]);
826 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100827 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
828#ifdef USE_ZLIB
829 if (*args[1]) {
830 global.tune.zlibmemlevel = atoi(args[1]);
831 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
832 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
833 file, linenum, args[0]);
834 err_code |= ERR_ALERT | ERR_FATAL;
835 goto out;
836 }
837 } else {
838 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
839 file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
842 }
843#else
844 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
845 err_code |= ERR_ALERT | ERR_FATAL;
846 goto out;
847#endif
848 }
849 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
850#ifdef USE_ZLIB
851 if (*args[1]) {
852 global.tune.zlibwindowsize = atoi(args[1]);
853 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
854 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
855 file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859 } else {
860 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
861 file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
865#else
866 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
867 err_code |= ERR_ALERT | ERR_FATAL;
868 goto out;
869#endif
870 }
William Lallemandf3747832012-11-09 12:33:10 +0100871 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
872 if (*args[1]) {
873 global.tune.comp_maxlevel = atoi(args[1]);
874 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
875 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
876 file, linenum, args[0]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880 } else {
881 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
882 file, linenum, args[0]);
883 err_code |= ERR_ALERT | ERR_FATAL;
884 goto out;
885 }
886 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200887 else if (!strcmp(args[0], "uid")) {
888 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200889 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200890 err_code |= ERR_ALERT;
891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 }
893 if (*(args[1]) == 0) {
894 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200895 err_code |= ERR_ALERT | ERR_FATAL;
896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897 }
898 global.uid = atol(args[1]);
899 }
900 else if (!strcmp(args[0], "gid")) {
901 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200902 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200903 err_code |= ERR_ALERT;
904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200905 }
906 if (*(args[1]) == 0) {
907 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910 }
911 global.gid = atol(args[1]);
912 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200913 /* user/group name handling */
914 else if (!strcmp(args[0], "user")) {
915 struct passwd *ha_user;
916 if (global.uid != 0) {
917 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200918 err_code |= ERR_ALERT;
919 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200920 }
921 errno = 0;
922 ha_user = getpwnam(args[1]);
923 if (ha_user != NULL) {
924 global.uid = (int)ha_user->pw_uid;
925 }
926 else {
927 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 +0200928 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200929 }
930 }
931 else if (!strcmp(args[0], "group")) {
932 struct group *ha_group;
933 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200934 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT;
936 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200937 }
938 errno = 0;
939 ha_group = getgrnam(args[1]);
940 if (ha_group != NULL) {
941 global.gid = (int)ha_group->gr_gid;
942 }
943 else {
944 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 +0200945 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200946 }
947 }
948 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950 if (*(args[1]) == 0) {
951 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 }
955 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100956 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
957 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
958 file, linenum, args[0], LONGBITS, global.nbproc);
959 err_code |= ERR_ALERT | ERR_FATAL;
960 goto out;
961 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962 }
963 else if (!strcmp(args[0], "maxconn")) {
964 if (global.maxconn != 0) {
965 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200966 err_code |= ERR_ALERT;
967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 }
969 if (*(args[1]) == 0) {
970 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200971 err_code |= ERR_ALERT | ERR_FATAL;
972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
974 global.maxconn = atol(args[1]);
975#ifdef SYSTEM_MAXCONN
976 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
977 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);
978 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200979 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980 }
981#endif /* SYSTEM_MAXCONN */
982 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200983 else if (!strcmp(args[0], "maxsslconn")) {
984#ifdef USE_OPENSSL
985 if (*(args[1]) == 0) {
986 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
987 err_code |= ERR_ALERT | ERR_FATAL;
988 goto out;
989 }
990 global.maxsslconn = atol(args[1]);
991#else
Emeric Brun0914df82012-10-02 18:45:42 +0200992 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
993 err_code |= ERR_ALERT | ERR_FATAL;
994 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200995#endif
996 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100997 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
998#ifdef USE_OPENSSL
999 if (*(args[1]) == 0) {
1000 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1001 err_code |= ERR_ALERT | ERR_FATAL;
1002 goto out;
1003 }
1004 free(global.listen_default_ciphers);
1005 global.listen_default_ciphers = strdup(args[1]);
1006#else
1007 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1008 err_code |= ERR_ALERT | ERR_FATAL;
1009 goto out;
1010#endif
1011 }
1012 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1013#ifdef USE_OPENSSL
1014 if (*(args[1]) == 0) {
1015 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1016 err_code |= ERR_ALERT | ERR_FATAL;
1017 goto out;
1018 }
1019 free(global.connect_default_ciphers);
1020 global.connect_default_ciphers = strdup(args[1]);
1021#else
1022 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
1025#endif
1026 }
Emeric Brun850efd52014-01-29 12:24:34 +01001027 else if (!strcmp(args[0], "ssl-server-verify")) {
1028 if (*(args[1]) == 0) {
1029 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1030 err_code |= ERR_ALERT | ERR_FATAL;
1031 goto out;
1032 }
1033 if (strcmp(args[1],"none") == 0)
1034 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1035 else if (strcmp(args[1],"required") == 0)
1036 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1037 else {
1038 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1039 err_code |= ERR_ALERT | ERR_FATAL;
1040 goto out;
1041 }
1042 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001043 else if (!strcmp(args[0], "maxconnrate")) {
1044 if (global.cps_lim != 0) {
1045 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1046 err_code |= ERR_ALERT;
1047 goto out;
1048 }
1049 if (*(args[1]) == 0) {
1050 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1051 err_code |= ERR_ALERT | ERR_FATAL;
1052 goto out;
1053 }
1054 global.cps_lim = atol(args[1]);
1055 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001056 else if (!strcmp(args[0], "maxsessrate")) {
1057 if (global.sps_lim != 0) {
1058 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1059 err_code |= ERR_ALERT;
1060 goto out;
1061 }
1062 if (*(args[1]) == 0) {
1063 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1064 err_code |= ERR_ALERT | ERR_FATAL;
1065 goto out;
1066 }
1067 global.sps_lim = atol(args[1]);
1068 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001069 else if (!strcmp(args[0], "maxsslrate")) {
1070 if (global.ssl_lim != 0) {
1071 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1072 err_code |= ERR_ALERT;
1073 goto out;
1074 }
1075 if (*(args[1]) == 0) {
1076 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1077 err_code |= ERR_ALERT | ERR_FATAL;
1078 goto out;
1079 }
1080 global.ssl_lim = atol(args[1]);
1081 }
William Lallemandd85f9172012-11-09 17:05:39 +01001082 else if (!strcmp(args[0], "maxcomprate")) {
1083 if (*(args[1]) == 0) {
1084 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1085 err_code |= ERR_ALERT | ERR_FATAL;
1086 goto out;
1087 }
1088 global.comp_rate_lim = atoi(args[1]) * 1024;
1089 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001090 else if (!strcmp(args[0], "maxpipes")) {
1091 if (global.maxpipes != 0) {
1092 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001093 err_code |= ERR_ALERT;
1094 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001095 }
1096 if (*(args[1]) == 0) {
1097 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001098 err_code |= ERR_ALERT | ERR_FATAL;
1099 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001100 }
1101 global.maxpipes = atol(args[1]);
1102 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001103 else if (!strcmp(args[0], "maxzlibmem")) {
1104 if (*(args[1]) == 0) {
1105 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1106 err_code |= ERR_ALERT | ERR_FATAL;
1107 goto out;
1108 }
William Lallemande3a7d992012-11-20 11:25:20 +01001109 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001110 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001111 else if (!strcmp(args[0], "maxcompcpuusage")) {
1112 if (*(args[1]) == 0) {
1113 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1114 err_code |= ERR_ALERT | ERR_FATAL;
1115 goto out;
1116 }
1117 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001118 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001119 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1120 err_code |= ERR_ALERT | ERR_FATAL;
1121 goto out;
1122 }
1123}
1124
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 else if (!strcmp(args[0], "ulimit-n")) {
1126 if (global.rlimit_nofile != 0) {
1127 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001128 err_code |= ERR_ALERT;
1129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001130 }
1131 if (*(args[1]) == 0) {
1132 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001135 }
1136 global.rlimit_nofile = atol(args[1]);
1137 }
1138 else if (!strcmp(args[0], "chroot")) {
1139 if (global.chroot != NULL) {
1140 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001141 err_code |= ERR_ALERT;
1142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143 }
1144 if (*(args[1]) == 0) {
1145 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001146 err_code |= ERR_ALERT | ERR_FATAL;
1147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001148 }
1149 global.chroot = strdup(args[1]);
1150 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001151 else if (!strcmp(args[0], "description")) {
1152 int i, len=0;
1153 char *d;
1154
1155 if (!*args[1]) {
1156 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1157 file, linenum, args[0]);
1158 err_code |= ERR_ALERT | ERR_FATAL;
1159 goto out;
1160 }
1161
Willy Tarreau348acfe2014-04-14 15:00:39 +02001162 for (i = 1; *args[i]; i++)
1163 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001164
1165 if (global.desc)
1166 free(global.desc);
1167
1168 global.desc = d = (char *)calloc(1, len);
1169
Willy Tarreau348acfe2014-04-14 15:00:39 +02001170 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1171 for (i = 2; *args[i]; i++)
1172 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001173 }
1174 else if (!strcmp(args[0], "node")) {
1175 int i;
1176 char c;
1177
1178 for (i=0; args[1][i]; i++) {
1179 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001180 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1181 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001182 break;
1183 }
1184
1185 if (!i || args[1][i]) {
1186 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1187 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1188 file, linenum, args[0]);
1189 err_code |= ERR_ALERT | ERR_FATAL;
1190 goto out;
1191 }
1192
1193 if (global.node)
1194 free(global.node);
1195
1196 global.node = strdup(args[1]);
1197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001198 else if (!strcmp(args[0], "pidfile")) {
1199 if (global.pidfile != NULL) {
1200 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001201 err_code |= ERR_ALERT;
1202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203 }
1204 if (*(args[1]) == 0) {
1205 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001206 err_code |= ERR_ALERT | ERR_FATAL;
1207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001208 }
1209 global.pidfile = strdup(args[1]);
1210 }
Emeric Bruned760922010-10-22 17:59:25 +02001211 else if (!strcmp(args[0], "unix-bind")) {
1212 int cur_arg = 1;
1213 while (*(args[cur_arg])) {
1214 if (!strcmp(args[cur_arg], "prefix")) {
1215 if (global.unix_bind.prefix != NULL) {
1216 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1217 err_code |= ERR_ALERT;
1218 cur_arg += 2;
1219 continue;
1220 }
1221
1222 if (*(args[cur_arg+1]) == 0) {
1223 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1224 err_code |= ERR_ALERT | ERR_FATAL;
1225 goto out;
1226 }
1227 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1228 cur_arg += 2;
1229 continue;
1230 }
1231
1232 if (!strcmp(args[cur_arg], "mode")) {
1233
1234 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1235 cur_arg += 2;
1236 continue;
1237 }
1238
1239 if (!strcmp(args[cur_arg], "uid")) {
1240
1241 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1242 cur_arg += 2;
1243 continue;
1244 }
1245
1246 if (!strcmp(args[cur_arg], "gid")) {
1247
1248 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1249 cur_arg += 2;
1250 continue;
1251 }
1252
1253 if (!strcmp(args[cur_arg], "user")) {
1254 struct passwd *user;
1255
1256 user = getpwnam(args[cur_arg + 1]);
1257 if (!user) {
1258 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1259 file, linenum, args[0], args[cur_arg + 1 ]);
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
1262 }
1263
1264 global.unix_bind.ux.uid = user->pw_uid;
1265 cur_arg += 2;
1266 continue;
1267 }
1268
1269 if (!strcmp(args[cur_arg], "group")) {
1270 struct group *group;
1271
1272 group = getgrnam(args[cur_arg + 1]);
1273 if (!group) {
1274 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1275 file, linenum, args[0], args[cur_arg + 1 ]);
1276 err_code |= ERR_ALERT | ERR_FATAL;
1277 goto out;
1278 }
1279
1280 global.unix_bind.ux.gid = group->gr_gid;
1281 cur_arg += 2;
1282 continue;
1283 }
1284
Willy Tarreaub48f9582011-09-05 01:17:06 +02001285 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001286 file, linenum, args[0]);
1287 err_code |= ERR_ALERT | ERR_FATAL;
1288 goto out;
1289 }
1290 }
William Lallemand0f99e342011-10-12 17:50:54 +02001291 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1292 /* delete previous herited or defined syslog servers */
1293 struct logsrv *back;
1294 struct logsrv *tmp;
1295
1296 if (*(args[1]) != 0) {
1297 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1298 err_code |= ERR_ALERT | ERR_FATAL;
1299 goto out;
1300 }
1301
1302 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1303 LIST_DEL(&tmp->list);
1304 free(tmp);
1305 }
1306 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001307 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001308 struct sockaddr_storage *sk;
1309 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001310 struct logsrv *logsrv;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001311 int arg = 0;
1312 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001313
Willy Tarreaubaaee002006-06-26 02:48:02 +02001314 if (*(args[1]) == 0 || *(args[2]) == 0) {
1315 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001316 err_code |= ERR_ALERT | ERR_FATAL;
1317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318 }
William Lallemand0f99e342011-10-12 17:50:54 +02001319
1320 logsrv = calloc(1, sizeof(struct logsrv));
1321
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001322 /* just after the address, a length may be specified */
1323 if (strcmp(args[arg+2], "len") == 0) {
1324 len = atoi(args[arg+3]);
1325 if (len < 80 || len > 65535) {
1326 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1327 file, linenum, args[arg+3]);
1328 err_code |= ERR_ALERT | ERR_FATAL;
1329 goto out;
1330 }
1331 logsrv->maxlen = len;
1332
1333 /* skip these two args */
1334 arg += 2;
1335 }
1336 else
1337 logsrv->maxlen = MAX_SYSLOG_LEN;
1338
1339 if (logsrv->maxlen > global.max_syslog_len) {
1340 global.max_syslog_len = logsrv->maxlen;
1341 logline = realloc(logline, global.max_syslog_len + 1);
1342 }
1343
1344 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001345 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001346 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001347 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001348 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 }
1350
William Lallemand0f99e342011-10-12 17:50:54 +02001351 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001352 if (*(args[arg+3])) {
1353 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001354 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001355 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001356 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001357 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 }
1359 }
1360
William Lallemand0f99e342011-10-12 17:50:54 +02001361 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001362 if (*(args[arg+4])) {
1363 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001364 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001365 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001366 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001367 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001368 }
1369 }
1370
Willy Tarreau902636f2013-03-10 19:44:48 +01001371 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001372 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001373 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001374 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001375 free(logsrv);
1376 goto out;
1377 }
1378 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001379
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001380 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001381 if (port1 != port2) {
1382 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1383 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001384 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001385 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001386 goto out;
1387 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001388
William Lallemand0f99e342011-10-12 17:50:54 +02001389 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001390 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001391 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001392 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001393
William Lallemand0f99e342011-10-12 17:50:54 +02001394 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001395 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001396 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1397 char *name;
1398 int len;
1399
1400 if (global.log_send_hostname != NULL) {
1401 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1402 err_code |= ERR_ALERT;
1403 goto out;
1404 }
1405
1406 if (*(args[1]))
1407 name = args[1];
1408 else
1409 name = hostname;
1410
1411 len = strlen(name);
1412
1413 /* We'll add a space after the name to respect the log format */
1414 free(global.log_send_hostname);
1415 global.log_send_hostname = malloc(len + 2);
1416 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1417 }
Kevinm48936af2010-12-22 16:08:21 +00001418 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1419 if (*(args[1]) == 0) {
1420 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1421 err_code |= ERR_ALERT | ERR_FATAL;
1422 goto out;
1423 }
1424 free(global.log_tag);
1425 global.log_tag = strdup(args[1]);
1426 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001427 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1428 if (global.spread_checks != 0) {
1429 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001430 err_code |= ERR_ALERT;
1431 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001432 }
1433 if (*(args[1]) == 0) {
1434 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001435 err_code |= ERR_ALERT | ERR_FATAL;
1436 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001437 }
1438 global.spread_checks = atol(args[1]);
1439 if (global.spread_checks < 0 || global.spread_checks > 50) {
1440 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001441 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001442 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001443 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001444 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1445 const char *err;
1446 unsigned int val;
1447
1448
1449 if (*(args[1]) == 0) {
1450 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1451 err_code |= ERR_ALERT | ERR_FATAL;
1452 goto out;
1453 }
1454
1455 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1456 if (err) {
1457 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1458 err_code |= ERR_ALERT | ERR_FATAL;
1459 }
1460 global.max_spread_checks = val;
1461 if (global.max_spread_checks < 0) {
1462 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1463 err_code |= ERR_ALERT | ERR_FATAL;
1464 }
1465 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001466 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1467#ifdef USE_CPU_AFFINITY
1468 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001469 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001470 unsigned long cpus = 0;
1471
1472 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001473 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001474 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001475 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001476 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001477 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001478 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001479 proc = atol(args[1]);
1480 if (proc >= 1 && proc <= LONGBITS)
1481 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001482 }
1483
1484 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001485 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",
1486 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001487 err_code |= ERR_ALERT | ERR_FATAL;
1488 goto out;
1489 }
1490
1491 cur_arg = 2;
1492 while (*args[cur_arg]) {
1493 unsigned int low, high;
1494
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001495 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001496 char *dash = strchr(args[cur_arg], '-');
1497
1498 low = high = str2uic(args[cur_arg]);
1499 if (dash)
1500 high = str2uic(dash + 1);
1501
1502 if (high < low) {
1503 unsigned int swap = low;
1504 low = high;
1505 high = swap;
1506 }
1507
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001508 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001509 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001510 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001511 err_code |= ERR_ALERT | ERR_FATAL;
1512 goto out;
1513 }
1514
1515 while (low <= high)
1516 cpus |= 1UL << low++;
1517 }
1518 else {
1519 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1520 file, linenum, args[0], args[cur_arg]);
1521 err_code |= ERR_ALERT | ERR_FATAL;
1522 goto out;
1523 }
1524 cur_arg++;
1525 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001526 for (i = 0; i < LONGBITS; i++)
1527 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001528 global.cpu_map[i] = cpus;
1529#else
1530 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1531 err_code |= ERR_ALERT | ERR_FATAL;
1532 goto out;
1533#endif
1534 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001535 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001536 struct cfg_kw_list *kwl;
1537 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001538 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001539
1540 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1541 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1542 if (kwl->kw[index].section != CFG_GLOBAL)
1543 continue;
1544 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001545 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001546 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001547 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001548 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001549 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001550 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001551 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001552 err_code |= ERR_WARN;
1553 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001554 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001555 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001556 }
1557 }
1558 }
1559
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001561 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001563
Willy Tarreau058e9072009-07-20 09:30:05 +02001564 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001565 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001566 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001567}
1568
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001569void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001571 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001572 defproxy.mode = PR_MODE_TCP;
1573 defproxy.state = PR_STNEW;
1574 defproxy.maxconn = cfg_maxpconn;
1575 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001576
Simon Horman66183002013-02-23 10:16:43 +09001577 defproxy.defsrv.check.inter = DEF_CHKINTR;
1578 defproxy.defsrv.check.fastinter = 0;
1579 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001580 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1581 defproxy.defsrv.agent.fastinter = 0;
1582 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001583 defproxy.defsrv.check.rise = DEF_RISETIME;
1584 defproxy.defsrv.check.fall = DEF_FALLTIME;
1585 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1586 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001587 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001588 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001589 defproxy.defsrv.maxqueue = 0;
1590 defproxy.defsrv.minconn = 0;
1591 defproxy.defsrv.maxconn = 0;
1592 defproxy.defsrv.slowstart = 0;
1593 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1594 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1595 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596}
1597
Willy Tarreauade5ec42010-01-28 19:33:49 +01001598
Willy Tarreau63af98d2014-05-18 08:11:41 +02001599/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1600 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1601 * ERR_FATAL in case of error.
1602 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001603static int create_cond_regex_rule(const char *file, int line,
1604 struct proxy *px, int dir, int action, int flags,
1605 const char *cmd, const char *reg, const char *repl,
1606 const char **cond_start)
1607{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001608 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001609 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001610 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001611 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001612 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001613 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001614 int cs;
1615 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001616
1617 if (px == &defproxy) {
1618 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001619 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001620 goto err;
1621 }
1622
1623 if (*reg == 0) {
1624 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001625 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001626 goto err;
1627 }
1628
1629 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001630 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001631
Willy Tarreau5321c422010-01-28 20:35:13 +01001632 if (cond_start &&
1633 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001634 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1635 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1636 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001637 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001638 goto err;
1639 }
1640 }
1641 else if (cond_start && **cond_start) {
1642 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1643 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001644 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001645 goto err;
1646 }
1647
Willy Tarreau63af98d2014-05-18 08:11:41 +02001648 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001649 (dir == SMP_OPT_DIR_REQ) ?
1650 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1651 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1652 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001653
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001654 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001655 if (!preg) {
1656 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001657 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001658 goto err;
1659 }
1660
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001661 cs = !(flags & REG_ICASE);
1662 cap = !(flags & REG_NOSUB);
1663 error = NULL;
1664 if (!regex_comp(reg, preg, cs, cap, &error)) {
1665 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1666 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001667 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001668 goto err;
1669 }
1670
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001671 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001672 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001673 if (repl && err) {
1674 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1675 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001676 ret_code |= ERR_ALERT | ERR_FATAL;
1677 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001678 }
1679
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001680 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001681 ret_code |= ERR_WARN;
1682
1683 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001684
Willy Tarreau63af98d2014-05-18 08:11:41 +02001685 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001686 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001687 err:
1688 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001689 free(errmsg);
1690 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001691}
1692
Willy Tarreaubaaee002006-06-26 02:48:02 +02001693/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001694 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001695 * Returns the error code, 0 if OK, or any combination of :
1696 * - ERR_ABORT: must abort ASAP
1697 * - ERR_FATAL: we can continue parsing but not start the service
1698 * - ERR_WARN: a warning has been emitted
1699 * - ERR_ALERT: an alert has been emitted
1700 * Only the two first ones can stop processing, the two others are just
1701 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001702 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001703int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1704{
1705 static struct peers *curpeers = NULL;
1706 struct peer *newpeer = NULL;
1707 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001708 struct bind_conf *bind_conf;
1709 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001710 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001711 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001712
1713 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001714 if (!*args[1]) {
1715 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001716 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001717 goto out;
1718 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001719
1720 err = invalid_char(args[1]);
1721 if (err) {
1722 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1723 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001724 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001725 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001726 }
1727
1728 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1729 /*
1730 * If there are two proxies with the same name only following
1731 * combinations are allowed:
1732 */
1733 if (strcmp(curpeers->id, args[1]) == 0) {
1734 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1735 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1736 err_code |= ERR_WARN;
1737 }
1738 }
1739
1740 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1741 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1742 err_code |= ERR_ALERT | ERR_ABORT;
1743 goto out;
1744 }
1745
1746 curpeers->next = peers;
1747 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001748 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001749 curpeers->conf.line = linenum;
1750 curpeers->last_change = now.tv_sec;
1751 curpeers->id = strdup(args[1]);
Willy Tarreau34d05b02015-05-01 20:02:17 +02001752 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001753 }
1754 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001755 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001756 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001757 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001758
1759 if (!*args[2]) {
1760 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1761 file, linenum, args[0]);
1762 err_code |= ERR_ALERT | ERR_FATAL;
1763 goto out;
1764 }
1765
1766 err = invalid_char(args[1]);
1767 if (err) {
1768 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1769 file, linenum, *err, args[1]);
1770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
1772 }
1773
1774 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1775 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1776 err_code |= ERR_ALERT | ERR_ABORT;
1777 goto out;
1778 }
1779
1780 /* the peers are linked backwards first */
1781 curpeers->count++;
1782 newpeer->next = curpeers->remote;
1783 curpeers->remote = newpeer;
1784 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001785 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001786 newpeer->conf.line = linenum;
1787
1788 newpeer->last_change = now.tv_sec;
1789 newpeer->id = strdup(args[1]);
1790
Willy Tarreau902636f2013-03-10 19:44:48 +01001791 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001792 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001793 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001794 err_code |= ERR_ALERT | ERR_FATAL;
1795 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001796 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001797
1798 proto = protocol_by_family(sk->ss_family);
1799 if (!proto || !proto->connect) {
1800 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1801 file, linenum, args[0], args[1]);
1802 err_code |= ERR_ALERT | ERR_FATAL;
1803 goto out;
1804 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001805
1806 if (port1 != port2) {
1807 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1808 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001809 err_code |= ERR_ALERT | ERR_FATAL;
1810 goto out;
1811 }
1812
Willy Tarreau2aa38802013-02-20 19:20:59 +01001813 if (!port1) {
1814 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1815 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001816 err_code |= ERR_ALERT | ERR_FATAL;
1817 goto out;
1818 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001819
Emeric Brun32da3c42010-09-23 18:39:19 +02001820 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001821 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001822 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001823 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001824
Emeric Brun32da3c42010-09-23 18:39:19 +02001825 if (strcmp(newpeer->id, localpeer) == 0) {
1826 /* Current is local peer, it define a frontend */
1827 newpeer->local = 1;
1828
1829 if (!curpeers->peers_fe) {
1830 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1831 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1832 err_code |= ERR_ALERT | ERR_ABORT;
1833 goto out;
1834 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001835
Willy Tarreau237250c2011-07-29 01:49:03 +02001836 init_new_proxy(curpeers->peers_fe);
1837 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001838
1839 curpeers->peers_fe->last_change = now.tv_sec;
1840 curpeers->peers_fe->id = strdup(args[1]);
1841 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001842 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001843 curpeers->peers_fe->conn_retries = CONN_RETRIES;
Willy Tarreaufc940eb2015-03-13 16:18:25 +01001844 curpeers->peers_fe->timeout.client = MS_TO_TICKS(5000);
Emeric Brun32da3c42010-09-23 18:39:19 +02001845 curpeers->peers_fe->accept = peer_accept;
1846 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001847 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1848 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreaucdb5e922015-05-01 19:12:05 +02001849 curpeers->peers_fe->bind_proc = 0; /* will be filled by users */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001850
1851 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1852
Willy Tarreau902636f2013-03-10 19:44:48 +01001853 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1854 if (errmsg && *errmsg) {
1855 indent_msg(&errmsg, 2);
1856 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001857 }
1858 else
1859 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1860 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001861 err_code |= ERR_FATAL;
1862 goto out;
1863 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001864
1865 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001866 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001867 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1868 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1869 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1870 l->accept = session_accept;
1871 l->handler = process_session;
1872 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1873 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1874 global.maxsock += l->maxconn;
1875 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001876 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001877 else {
1878 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1879 file, linenum, args[0], args[1],
1880 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1881 err_code |= ERR_FATAL;
1882 goto out;
1883 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001884 }
1885 } /* neither "peer" nor "peers" */
Willy Tarreau34d05b02015-05-01 20:02:17 +02001886 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
1887 curpeers->state = PR_STSTOPPED;
1888 }
1889 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
1890 curpeers->state = PR_STNEW;
1891 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001892 else if (*args[0] != 0) {
1893 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1894 err_code |= ERR_ALERT | ERR_FATAL;
1895 goto out;
1896 }
1897
1898out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001899 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001900 return err_code;
1901}
1902
Willy Tarreau3842f002009-06-14 11:39:52 +02001903int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001904{
1905 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001906 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001907 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001908 int rc;
1909 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001910 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001911 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001912 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001913 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001914 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915
Willy Tarreau977b8e42006-12-29 14:19:17 +01001916 if (!strcmp(args[0], "listen"))
1917 rc = PR_CAP_LISTEN;
1918 else if (!strcmp(args[0], "frontend"))
1919 rc = PR_CAP_FE | PR_CAP_RS;
1920 else if (!strcmp(args[0], "backend"))
1921 rc = PR_CAP_BE | PR_CAP_RS;
1922 else if (!strcmp(args[0], "ruleset"))
1923 rc = PR_CAP_RS;
1924 else
1925 rc = PR_CAP_NONE;
1926
1927 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001928 struct ebpt_node *node;
1929
Willy Tarreaubaaee002006-06-26 02:48:02 +02001930 if (!*args[1]) {
1931 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1932 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1933 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001934 err_code |= ERR_ALERT | ERR_ABORT;
1935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001937
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001938 err = invalid_char(args[1]);
1939 if (err) {
1940 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1941 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001942 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001943 }
1944
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001945 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1946 curproxy = container_of(node, struct proxy, conf.by_name);
1947
1948 if (strcmp(curproxy->id, args[1]) != 0)
1949 break;
1950
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001951 /*
1952 * If there are two proxies with the same name only following
1953 * combinations are allowed:
1954 *
1955 * listen backend frontend ruleset
1956 * listen - - - -
1957 * backend - - OK -
1958 * frontend - OK - -
1959 * ruleset - - - -
1960 */
1961
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001962 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1963 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001964 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1965 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1966 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001967 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001968 }
1969 }
1970
Willy Tarreaubaaee002006-06-26 02:48:02 +02001971 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1972 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001973 err_code |= ERR_ALERT | ERR_ABORT;
1974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001975 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001976
Willy Tarreau97cb7802010-01-03 20:23:58 +01001977 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001978 curproxy->next = proxy;
1979 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001980 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1981 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001982 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001983 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001984 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001985 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001986
1987 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001988 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001989 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001990
Willy Tarreau4348fad2012-09-20 16:48:07 +02001991 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1992
Willy Tarreau902636f2013-03-10 19:44:48 +01001993 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1994 if (errmsg && *errmsg) {
1995 indent_msg(&errmsg, 2);
1996 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001997 }
1998 else
1999 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2000 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002001 err_code |= ERR_FATAL;
2002 goto out;
2003 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002004
Willy Tarreau4348fad2012-09-20 16:48:07 +02002005 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002006 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002007 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002008 }
2009
2010 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002011 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002012 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002013
Willy Tarreaubaaee002006-06-26 02:48:02 +02002014 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002015 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002016 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002017 curproxy->no_options = defproxy.no_options;
2018 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002019 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002020 curproxy->except_net = defproxy.except_net;
2021 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002022 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002023 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002024
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002025 if (defproxy.fwdfor_hdr_len) {
2026 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2027 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2028 }
2029
Willy Tarreaub86db342009-11-30 11:50:16 +01002030 if (defproxy.orgto_hdr_len) {
2031 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2032 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2033 }
2034
Mark Lamourinec2247f02012-01-04 13:02:01 -05002035 if (defproxy.server_id_hdr_len) {
2036 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2037 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2038 }
2039
Willy Tarreau977b8e42006-12-29 14:19:17 +01002040 if (curproxy->cap & PR_CAP_FE) {
2041 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002042 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002043 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002044
2045 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002046 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2047 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002048
2049 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002051
Willy Tarreau977b8e42006-12-29 14:19:17 +01002052 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaucac307c2014-11-18 15:04:29 +01002053 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002054 curproxy->fullconn = defproxy.fullconn;
2055 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002056 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002057
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002058 if (defproxy.check_req) {
2059 curproxy->check_req = calloc(1, defproxy.check_len);
2060 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2061 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002062 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002063
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002064 if (defproxy.expect_str) {
2065 curproxy->expect_str = strdup(defproxy.expect_str);
2066 if (defproxy.expect_regex) {
2067 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002068 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2069 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002070 }
2071 }
2072
Willy Tarreau67402132012-05-31 20:40:20 +02002073 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002074 if (defproxy.cookie_name)
2075 curproxy->cookie_name = strdup(defproxy.cookie_name);
2076 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002077 if (defproxy.cookie_domain)
2078 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002079
Willy Tarreau31936852010-10-06 16:59:56 +02002080 if (defproxy.cookie_maxidle)
2081 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2082
2083 if (defproxy.cookie_maxlife)
2084 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2085
Emeric Brun647caf12009-06-30 17:57:00 +02002086 if (defproxy.rdp_cookie_name)
2087 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2088 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2089
Willy Tarreau01732802007-11-01 22:48:15 +01002090 if (defproxy.url_param_name)
2091 curproxy->url_param_name = strdup(defproxy.url_param_name);
2092 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002093
Benoitaffb4812009-03-25 13:02:10 +01002094 if (defproxy.hh_name)
2095 curproxy->hh_name = strdup(defproxy.hh_name);
2096 curproxy->hh_len = defproxy.hh_len;
2097 curproxy->hh_match_domain = defproxy.hh_match_domain;
2098
Willy Tarreauef9a3602012-12-08 22:29:20 +01002099 if (defproxy.conn_src.iface_name)
2100 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2101 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002102 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002103#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002104 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002105#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002106 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002107
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002108 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002109 if (defproxy.capture_name)
2110 curproxy->capture_name = strdup(defproxy.capture_name);
2111 curproxy->capture_namelen = defproxy.capture_namelen;
2112 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002113 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002114
Willy Tarreau977b8e42006-12-29 14:19:17 +01002115 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002116 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002117 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002118 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002119 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002120 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002121 curproxy->mon_net = defproxy.mon_net;
2122 curproxy->mon_mask = defproxy.mon_mask;
2123 if (defproxy.monitor_uri)
2124 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2125 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002126 if (defproxy.defbe.name)
2127 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002128
2129 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002130 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2131 if (curproxy->conf.logformat_string &&
2132 curproxy->conf.logformat_string != default_http_log_format &&
2133 curproxy->conf.logformat_string != default_tcp_log_format &&
2134 curproxy->conf.logformat_string != clf_http_log_format)
2135 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2136
2137 if (defproxy.conf.lfs_file) {
2138 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2139 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2140 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002141 }
2142
2143 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002144 curproxy->timeout.connect = defproxy.timeout.connect;
2145 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002146 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002147 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002148 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002149 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002150 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002151 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002152 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002153 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002154 }
2155
Willy Tarreaubaaee002006-06-26 02:48:02 +02002156 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002157 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002158
2159 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002160 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002161 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002162 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002163 LIST_INIT(&node->list);
2164 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2165 }
2166
Willy Tarreau62a61232013-04-12 18:13:46 +02002167 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2168 if (curproxy->conf.uniqueid_format_string)
2169 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2170
2171 if (defproxy.conf.uif_file) {
2172 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2173 curproxy->conf.uif_line = defproxy.conf.uif_line;
2174 }
William Lallemanda73203e2012-03-12 12:48:57 +01002175
2176 /* copy default header unique id */
2177 if (defproxy.header_unique_id)
2178 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2179
William Lallemand82fe75c2012-10-23 10:25:10 +02002180 /* default compression options */
2181 if (defproxy.comp != NULL) {
2182 curproxy->comp = calloc(1, sizeof(struct comp));
2183 curproxy->comp->algos = defproxy.comp->algos;
2184 curproxy->comp->types = defproxy.comp->types;
2185 }
2186
Willy Tarreaubaaee002006-06-26 02:48:02 +02002187 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002188 curproxy->conf.used_listener_id = EB_ROOT;
2189 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002190
Willy Tarreau93893792009-07-23 13:19:11 +02002191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002192 }
2193 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2194 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002195 /* FIXME-20070101: we should do this too at the end of the
2196 * config parsing to free all default values.
2197 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002198 free(defproxy.check_req);
2199 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002200 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002201 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002202 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002203 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002204 free(defproxy.capture_name);
2205 free(defproxy.monitor_uri);
2206 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002207 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002208 free(defproxy.fwdfor_hdr_name);
2209 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002210 free(defproxy.orgto_hdr_name);
2211 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002212 free(defproxy.server_id_hdr_name);
2213 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002214 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002215 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002216 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002217 free(defproxy.expect_regex);
2218 defproxy.expect_regex = NULL;
2219 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002220
Willy Tarreau62a61232013-04-12 18:13:46 +02002221 if (defproxy.conf.logformat_string != default_http_log_format &&
2222 defproxy.conf.logformat_string != default_tcp_log_format &&
2223 defproxy.conf.logformat_string != clf_http_log_format)
2224 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002225
Willy Tarreau62a61232013-04-12 18:13:46 +02002226 free(defproxy.conf.uniqueid_format_string);
2227 free(defproxy.conf.lfs_file);
2228 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002229
Willy Tarreaua534fea2008-08-03 12:19:50 +02002230 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002231 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002232
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233 /* we cannot free uri_auth because it might already be used */
2234 init_default_instance();
2235 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002236 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2237 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002238 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240 }
2241 else if (curproxy == NULL) {
2242 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002246
2247 /* update the current file and line being parsed */
2248 curproxy->conf.args.file = curproxy->conf.file;
2249 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002250
2251 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002252 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2253 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2254 if (err_code & ERR_FATAL)
2255 goto out;
2256 }
2257 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002258 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002259 int cur_arg;
2260
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 if (curproxy == &defproxy) {
2262 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002263 err_code |= ERR_ALERT | ERR_FATAL;
2264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002266 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002267 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002268
Willy Tarreau24709282013-03-10 21:32:12 +01002269 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002270 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002271 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002274 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002275
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002276 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002277
2278 /* use default settings for unix sockets */
2279 bind_conf->ux.uid = global.unix_bind.ux.uid;
2280 bind_conf->ux.gid = global.unix_bind.ux.gid;
2281 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002282
2283 /* NOTE: the following line might create several listeners if there
2284 * are comma-separated IPs or port ranges. So all further processing
2285 * will have to be applied to all listeners created after last_listen.
2286 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002287 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2288 if (errmsg && *errmsg) {
2289 indent_msg(&errmsg, 2);
2290 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002291 }
2292 else
2293 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2294 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002295 err_code |= ERR_ALERT | ERR_FATAL;
2296 goto out;
2297 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002298
Willy Tarreau4348fad2012-09-20 16:48:07 +02002299 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2300 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002301 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002302 }
2303
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002304 cur_arg = 2;
2305 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002306 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002307 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002308 char *err;
2309
Willy Tarreau26982662012-09-12 23:17:10 +02002310 kw = bind_find_kw(args[cur_arg]);
2311 if (kw) {
2312 char *err = NULL;
2313 int code;
2314
2315 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002316 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2317 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002318 cur_arg += 1 + kw->skip ;
2319 err_code |= ERR_ALERT | ERR_FATAL;
2320 goto out;
2321 }
2322
Willy Tarreau4348fad2012-09-20 16:48:07 +02002323 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002324 err_code |= code;
2325
2326 if (code) {
2327 if (err && *err) {
2328 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002329 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002330 }
2331 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002332 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2333 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002334 if (code & ERR_FATAL) {
2335 free(err);
2336 cur_arg += 1 + kw->skip;
2337 goto out;
2338 }
2339 }
2340 free(err);
2341 cur_arg += 1 + kw->skip;
2342 continue;
2343 }
2344
Willy Tarreau8638f482012-09-18 18:01:17 +02002345 err = NULL;
2346 if (!bind_dumped) {
2347 bind_dump_kws(&err);
2348 indent_msg(&err, 4);
2349 bind_dumped = 1;
2350 }
2351
2352 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2353 file, linenum, args[0], args[1], args[cur_arg],
2354 err ? " Registered keywords :" : "", err ? err : "");
2355 free(err);
2356
Willy Tarreau93893792009-07-23 13:19:11 +02002357 err_code |= ERR_ALERT | ERR_FATAL;
2358 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002359 }
Willy Tarreau93893792009-07-23 13:19:11 +02002360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 }
2362 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002363 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2365 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002369 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002370 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002371
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 /* flush useless bits */
2373 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002374 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002376 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002377 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002378 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002379
Willy Tarreau1c47f852006-07-09 08:22:27 +02002380 if (!*args[1]) {
2381 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2382 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002385 }
2386
Willy Tarreaua534fea2008-08-03 12:19:50 +02002387 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002388 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002389 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002390 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002391 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2392
Willy Tarreau93893792009-07-23 13:19:11 +02002393 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002394 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2396 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2397 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2398 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2399 else {
2400 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002401 err_code |= ERR_ALERT | ERR_FATAL;
2402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 }
2404 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002405 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002406 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002407
2408 if (curproxy == &defproxy) {
2409 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2410 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002413 }
2414
2415 if (!*args[1]) {
2416 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2417 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002420 }
2421
2422 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002423 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002424
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002425 if (curproxy->uuid <= 0) {
2426 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002427 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002430 }
2431
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002432 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2433 if (node) {
2434 struct proxy *target = container_of(node, struct proxy, conf.id);
2435 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2436 file, linenum, proxy_type_str(curproxy), curproxy->id,
2437 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2438 err_code |= ERR_ALERT | ERR_FATAL;
2439 goto out;
2440 }
2441 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002442 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002443 else if (!strcmp(args[0], "description")) {
2444 int i, len=0;
2445 char *d;
2446
Cyril Bonté99ed3272010-01-24 23:29:44 +01002447 if (curproxy == &defproxy) {
2448 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2449 file, linenum, args[0]);
2450 err_code |= ERR_ALERT | ERR_FATAL;
2451 goto out;
2452 }
2453
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002454 if (!*args[1]) {
2455 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2456 file, linenum, args[0]);
2457 return -1;
2458 }
2459
Willy Tarreau348acfe2014-04-14 15:00:39 +02002460 for (i = 1; *args[i]; i++)
2461 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002462
2463 d = (char *)calloc(1, len);
2464 curproxy->desc = d;
2465
Willy Tarreau348acfe2014-04-14 15:00:39 +02002466 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2467 for (i = 2; *args[i]; i++)
2468 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002469
2470 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2472 curproxy->state = PR_STSTOPPED;
2473 }
2474 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2475 curproxy->state = PR_STNEW;
2476 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002477 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2478 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002479 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002480
2481 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002482 unsigned int low, high;
2483
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002484 if (strcmp(args[cur_arg], "all") == 0) {
2485 set = 0;
2486 break;
2487 }
2488 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002489 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002490 }
2491 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002492 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002493 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002494 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002495 char *dash = strchr(args[cur_arg], '-');
2496
2497 low = high = str2uic(args[cur_arg]);
2498 if (dash)
2499 high = str2uic(dash + 1);
2500
2501 if (high < low) {
2502 unsigned int swap = low;
2503 low = high;
2504 high = swap;
2505 }
2506
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002507 if (low < 1 || high > LONGBITS) {
2508 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2509 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002512 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002513 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002514 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002515 }
2516 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002517 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2518 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002521 }
2522 cur_arg++;
2523 }
2524 curproxy->bind_proc = set;
2525 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002526 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002527 if (curproxy == &defproxy) {
2528 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002529 err_code |= ERR_ALERT | ERR_FATAL;
2530 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002531 }
2532
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002533 err = invalid_char(args[1]);
2534 if (err) {
2535 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2536 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002537 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002538 }
2539
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002540 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002541 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2542 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002545 }
2546 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2548 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549
Willy Tarreau977b8e42006-12-29 14:19:17 +01002550 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002551 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002552
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 if (*(args[1]) == 0) {
2554 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2555 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002556 err_code |= ERR_ALERT | ERR_FATAL;
2557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002558 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002559
Willy Tarreau67402132012-05-31 20:40:20 +02002560 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002561 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002562 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002563 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 curproxy->cookie_name = strdup(args[1]);
2565 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002566
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 cur_arg = 2;
2568 while (*(args[cur_arg])) {
2569 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002570 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 }
2572 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002573 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 }
2575 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002576 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 }
2578 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002579 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 }
2581 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002582 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002584 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002585 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002588 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002590 else if (!strcmp(args[cur_arg], "httponly")) {
2591 curproxy->ck_opts |= PR_CK_HTTPONLY;
2592 }
2593 else if (!strcmp(args[cur_arg], "secure")) {
2594 curproxy->ck_opts |= PR_CK_SECURE;
2595 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002596 else if (!strcmp(args[cur_arg], "domain")) {
2597 if (!*args[cur_arg + 1]) {
2598 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2599 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002600 err_code |= ERR_ALERT | ERR_FATAL;
2601 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002602 }
2603
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002604 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002605 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002606 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2607 " dots nor does not start with a dot."
2608 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002609 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002610 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002611 }
2612
2613 err = invalid_domainchar(args[cur_arg + 1]);
2614 if (err) {
2615 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2616 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002617 err_code |= ERR_ALERT | ERR_FATAL;
2618 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002619 }
2620
Willy Tarreau68a897b2009-12-03 23:28:34 +01002621 if (!curproxy->cookie_domain) {
2622 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2623 } else {
2624 /* one domain was already specified, add another one by
2625 * building the string which will be returned along with
2626 * the cookie.
2627 */
2628 char *new_ptr;
2629 int new_len = strlen(curproxy->cookie_domain) +
2630 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2631 new_ptr = malloc(new_len);
2632 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2633 free(curproxy->cookie_domain);
2634 curproxy->cookie_domain = new_ptr;
2635 }
Willy Tarreau31936852010-10-06 16:59:56 +02002636 cur_arg++;
2637 }
2638 else if (!strcmp(args[cur_arg], "maxidle")) {
2639 unsigned int maxidle;
2640 const char *res;
2641
2642 if (!*args[cur_arg + 1]) {
2643 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2644 file, linenum, args[cur_arg]);
2645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
2647 }
2648
2649 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2650 if (res) {
2651 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2652 file, linenum, *res, args[cur_arg]);
2653 err_code |= ERR_ALERT | ERR_FATAL;
2654 goto out;
2655 }
2656 curproxy->cookie_maxidle = maxidle;
2657 cur_arg++;
2658 }
2659 else if (!strcmp(args[cur_arg], "maxlife")) {
2660 unsigned int maxlife;
2661 const char *res;
2662
2663 if (!*args[cur_arg + 1]) {
2664 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2665 file, linenum, args[cur_arg]);
2666 err_code |= ERR_ALERT | ERR_FATAL;
2667 goto out;
2668 }
2669
2670 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2671 if (res) {
2672 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2673 file, linenum, *res, args[cur_arg]);
2674 err_code |= ERR_ALERT | ERR_FATAL;
2675 goto out;
2676 }
2677 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002678 cur_arg++;
2679 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002680 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002681 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 +02002682 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002685 }
2686 cur_arg++;
2687 }
Willy Tarreau67402132012-05-31 20:40:20 +02002688 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002689 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2690 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002691 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 }
2693
Willy Tarreau67402132012-05-31 20:40:20 +02002694 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002695 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2696 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002697 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002698 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002699
Willy Tarreau67402132012-05-31 20:40:20 +02002700 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002701 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2702 file, linenum);
2703 err_code |= ERR_ALERT | ERR_FATAL;
2704 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002706 else if (!strcmp(args[0], "persist")) { /* persist */
2707 if (*(args[1]) == 0) {
2708 Alert("parsing [%s:%d] : missing persist method.\n",
2709 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002712 }
2713
2714 if (!strncmp(args[1], "rdp-cookie", 10)) {
2715 curproxy->options2 |= PR_O2_RDPC_PRST;
2716
Emeric Brunb982a3d2010-01-04 15:45:53 +01002717 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002718 const char *beg, *end;
2719
2720 beg = args[1] + 11;
2721 end = strchr(beg, ')');
2722
2723 if (!end || end == beg) {
2724 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2725 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002726 err_code |= ERR_ALERT | ERR_FATAL;
2727 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002728 }
2729
2730 free(curproxy->rdp_cookie_name);
2731 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2732 curproxy->rdp_cookie_len = end-beg;
2733 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002734 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002735 free(curproxy->rdp_cookie_name);
2736 curproxy->rdp_cookie_name = strdup("msts");
2737 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2738 }
2739 else { /* syntax */
2740 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\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 else {
2747 Alert("parsing [%s:%d] : unknown persist method.\n",
2748 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002749 err_code |= ERR_ALERT | ERR_FATAL;
2750 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002751 }
2752 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002753 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002754 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002755
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002756 if (curproxy == &defproxy) {
2757 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
2760 }
2761
Willy Tarreau977b8e42006-12-29 14:19:17 +01002762 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002763 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002764
Willy Tarreaubaaee002006-06-26 02:48:02 +02002765 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002766 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002767 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002770 }
2771 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002772 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002773 curproxy->appsession_name = strdup(args[1]);
2774 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2775 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002776 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2777 if (err) {
2778 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2779 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002780 err_code |= ERR_ALERT | ERR_FATAL;
2781 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002782 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002783 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002784
Willy Tarreau51041c72007-09-09 21:56:53 +02002785 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2786 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002787 err_code |= ERR_ALERT | ERR_ABORT;
2788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002789 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002790
2791 cur_arg = 6;
2792 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002793 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2794 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002795 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002796 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002797 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002798 } else if (!strcmp(args[cur_arg], "prefix")) {
2799 curproxy->options2 |= PR_O2_AS_PFX;
2800 } else if (!strcmp(args[cur_arg], "mode")) {
2801 if (!*args[cur_arg + 1]) {
2802 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2803 file, linenum, args[0], args[cur_arg]);
2804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
2806 }
2807
2808 cur_arg++;
2809 if (!strcmp(args[cur_arg], "query-string")) {
2810 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2811 curproxy->options2 |= PR_O2_AS_M_QS;
2812 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2813 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2814 curproxy->options2 |= PR_O2_AS_M_PP;
2815 } else {
2816 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2817 err_code |= ERR_ALERT | ERR_FATAL;
2818 goto out;
2819 }
2820 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002821 cur_arg++;
2822 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002823 } /* Url App Session */
2824 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002825 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002826 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002827
Willy Tarreaubaaee002006-06-26 02:48:02 +02002828 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002829 if (curproxy == &defproxy) {
2830 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
2833 }
2834
Willy Tarreaubaaee002006-06-26 02:48:02 +02002835 if (*(args[4]) == 0) {
2836 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2837 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002838 err_code |= ERR_ALERT | ERR_FATAL;
2839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002841 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002842 curproxy->capture_name = strdup(args[2]);
2843 curproxy->capture_namelen = strlen(curproxy->capture_name);
2844 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002845 curproxy->to_log |= LW_COOKIE;
2846 }
2847 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2848 struct cap_hdr *hdr;
2849
2850 if (curproxy == &defproxy) {
2851 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 +02002852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002854 }
2855
2856 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2857 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2858 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002861 }
2862
2863 hdr = calloc(sizeof(struct cap_hdr), 1);
2864 hdr->next = curproxy->req_cap;
2865 hdr->name = strdup(args[3]);
2866 hdr->namelen = strlen(args[3]);
2867 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002868 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002869 hdr->index = curproxy->nb_req_cap++;
2870 curproxy->req_cap = hdr;
2871 curproxy->to_log |= LW_REQHDR;
2872 }
2873 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2874 struct cap_hdr *hdr;
2875
2876 if (curproxy == &defproxy) {
2877 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 +02002878 err_code |= ERR_ALERT | ERR_FATAL;
2879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002880 }
2881
2882 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2883 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2884 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002885 err_code |= ERR_ALERT | ERR_FATAL;
2886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002887 }
2888 hdr = calloc(sizeof(struct cap_hdr), 1);
2889 hdr->next = curproxy->rsp_cap;
2890 hdr->name = strdup(args[3]);
2891 hdr->namelen = strlen(args[3]);
2892 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002893 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002894 hdr->index = curproxy->nb_rsp_cap++;
2895 curproxy->rsp_cap = hdr;
2896 curproxy->to_log |= LW_RSPHDR;
2897 }
2898 else {
2899 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2900 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002901 err_code |= ERR_ALERT | ERR_FATAL;
2902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002903 }
2904 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002905 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002906 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002907 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002908
Willy Tarreaubaaee002006-06-26 02:48:02 +02002909 if (*(args[1]) == 0) {
2910 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2911 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002914 }
2915 curproxy->conn_retries = atol(args[1]);
2916 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002917 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002918 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002919
2920 if (curproxy == &defproxy) {
2921 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
2924 }
2925
Willy Tarreau20b0de52012-12-24 15:45:22 +01002926 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2927 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2928 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2929 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002930 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002931 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2932 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 +01002933 file, linenum, args[0]);
2934 err_code |= ERR_WARN;
2935 }
2936
Willy Tarreauff011f22011-01-06 17:51:27 +01002937 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002938
Willy Tarreauff011f22011-01-06 17:51:27 +01002939 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002940 err_code |= ERR_ALERT | ERR_ABORT;
2941 goto out;
2942 }
2943
Willy Tarreau5002f572014-04-23 01:32:02 +02002944 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002945 err_code |= warnif_cond_conflicts(rule->cond,
2946 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2947 file, linenum);
2948
Willy Tarreauff011f22011-01-06 17:51:27 +01002949 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002950 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002951 else if (!strcmp(args[0], "http-response")) { /* response access control */
2952 struct http_res_rule *rule;
2953
2954 if (curproxy == &defproxy) {
2955 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2956 err_code |= ERR_ALERT | ERR_FATAL;
2957 goto out;
2958 }
2959
2960 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2961 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2962 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2963 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2964 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2965 file, linenum, args[0]);
2966 err_code |= ERR_WARN;
2967 }
2968
2969 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2970
2971 if (!rule) {
2972 err_code |= ERR_ALERT | ERR_ABORT;
2973 goto out;
2974 }
2975
2976 err_code |= warnif_cond_conflicts(rule->cond,
2977 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2978 file, linenum);
2979
2980 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2981 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002982 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2983 /* set the header name and length into the proxy structure */
2984 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2985 err_code |= ERR_WARN;
2986
2987 if (!*args[1]) {
2988 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2989 file, linenum, args[0]);
2990 err_code |= ERR_ALERT | ERR_FATAL;
2991 goto out;
2992 }
2993
2994 /* set the desired header name */
2995 free(curproxy->server_id_hdr_name);
2996 curproxy->server_id_hdr_name = strdup(args[1]);
2997 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2998 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002999 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003000 struct http_req_rule *rule;
3001
Willy Tarreaub099aca2008-10-12 17:26:37 +02003002 if (curproxy == &defproxy) {
3003 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003006 }
3007
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003008 /* emulate "block" using "http-request block". Since these rules are supposed to
3009 * be processed before all http-request rules, we put them into their own list
3010 * and will insert them at the end.
3011 */
3012 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3013 if (!rule) {
3014 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003015 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003016 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003017 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3018 err_code |= warnif_cond_conflicts(rule->cond,
3019 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3020 file, linenum);
3021 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003022
3023 if (!already_warned(WARN_BLOCK_DEPRECATED))
3024 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]);
3025
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003026 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003027 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003028 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003029
Cyril Bonté99ed3272010-01-24 23:29:44 +01003030 if (curproxy == &defproxy) {
3031 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3032 err_code |= ERR_ALERT | ERR_FATAL;
3033 goto out;
3034 }
3035
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003036 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003037 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3038 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003041 }
3042
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003043 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003044 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003045 err_code |= warnif_cond_conflicts(rule->cond,
3046 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3047 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003048 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003049 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003050 struct switching_rule *rule;
3051
Willy Tarreaub099aca2008-10-12 17:26:37 +02003052 if (curproxy == &defproxy) {
3053 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003056 }
3057
Willy Tarreau55ea7572007-06-17 19:56:27 +02003058 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003060
3061 if (*(args[1]) == 0) {
3062 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003063 err_code |= ERR_ALERT | ERR_FATAL;
3064 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003065 }
3066
Willy Tarreauf51658d2014-04-23 01:21:56 +02003067 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3068 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3069 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3070 file, linenum, errmsg);
3071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
3073 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003074
Willy Tarreauf51658d2014-04-23 01:21:56 +02003075 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003076 }
3077
3078 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3079 rule->cond = cond;
3080 rule->be.name = strdup(args[1]);
3081 LIST_INIT(&rule->list);
3082 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3083 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003084 else if (strcmp(args[0], "use-server") == 0) {
3085 struct server_rule *rule;
3086
3087 if (curproxy == &defproxy) {
3088 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3089 err_code |= ERR_ALERT | ERR_FATAL;
3090 goto out;
3091 }
3092
3093 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3094 err_code |= ERR_WARN;
3095
3096 if (*(args[1]) == 0) {
3097 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3098 err_code |= ERR_ALERT | ERR_FATAL;
3099 goto out;
3100 }
3101
3102 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3103 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3104 file, linenum, args[0]);
3105 err_code |= ERR_ALERT | ERR_FATAL;
3106 goto out;
3107 }
3108
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003109 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3110 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3111 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003112 err_code |= ERR_ALERT | ERR_FATAL;
3113 goto out;
3114 }
3115
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003116 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003117
3118 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3119 rule->cond = cond;
3120 rule->srv.name = strdup(args[1]);
3121 LIST_INIT(&rule->list);
3122 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3123 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3124 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003125 else if ((!strcmp(args[0], "force-persist")) ||
3126 (!strcmp(args[0], "ignore-persist"))) {
3127 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003128
3129 if (curproxy == &defproxy) {
3130 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
3133 }
3134
3135 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3136 err_code |= ERR_WARN;
3137
Willy Tarreauef6494c2010-01-28 17:12:36 +01003138 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003139 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3140 file, linenum, args[0]);
3141 err_code |= ERR_ALERT | ERR_FATAL;
3142 goto out;
3143 }
3144
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003145 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3146 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3147 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
3150 }
3151
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003152 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3153 * where force-persist is applied.
3154 */
3155 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003156
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003157 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003158 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003159 if (!strcmp(args[0], "force-persist")) {
3160 rule->type = PERSIST_TYPE_FORCE;
3161 } else {
3162 rule->type = PERSIST_TYPE_IGNORE;
3163 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003164 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003165 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003166 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003167 else if (!strcmp(args[0], "stick-table")) {
3168 int myidx = 1;
3169
Emeric Brun32da3c42010-09-23 18:39:19 +02003170 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003171 curproxy->table.type = (unsigned int)-1;
3172 while (*args[myidx]) {
3173 const char *err;
3174
3175 if (strcmp(args[myidx], "size") == 0) {
3176 myidx++;
3177 if (!*(args[myidx])) {
3178 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3179 file, linenum, args[myidx-1]);
3180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
3182 }
3183 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3184 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3185 file, linenum, *err, args[myidx-1]);
3186 err_code |= ERR_ALERT | ERR_FATAL;
3187 goto out;
3188 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003189 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003190 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003191 else if (strcmp(args[myidx], "peers") == 0) {
3192 myidx++;
Godbach50523162013-12-11 19:48:57 +08003193 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003194 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3195 file, linenum, args[myidx-1]);
3196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
Godbach50523162013-12-11 19:48:57 +08003198 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003199 curproxy->table.peers.name = strdup(args[myidx++]);
3200 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003201 else if (strcmp(args[myidx], "expire") == 0) {
3202 myidx++;
3203 if (!*(args[myidx])) {
3204 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3205 file, linenum, args[myidx-1]);
3206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
3208 }
3209 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3210 if (err) {
3211 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3212 file, linenum, *err, args[myidx-1]);
3213 err_code |= ERR_ALERT | ERR_FATAL;
3214 goto out;
3215 }
3216 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003217 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003218 }
3219 else if (strcmp(args[myidx], "nopurge") == 0) {
3220 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003221 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003222 }
3223 else if (strcmp(args[myidx], "type") == 0) {
3224 myidx++;
3225 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3226 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3227 file, linenum, args[myidx]);
3228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
3230 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003231 /* myidx already points to next arg */
3232 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003233 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003234 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003235 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003236
3237 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003238 nw = args[myidx];
3239 while (*nw) {
3240 /* the "store" keyword supports a comma-separated list */
3241 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003242 sa = NULL; /* store arg */
3243 while (*nw && *nw != ',') {
3244 if (*nw == '(') {
3245 *nw = 0;
3246 sa = ++nw;
3247 while (*nw != ')') {
3248 if (!*nw) {
3249 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3250 file, linenum, args[0], cw);
3251 err_code |= ERR_ALERT | ERR_FATAL;
3252 goto out;
3253 }
3254 nw++;
3255 }
3256 *nw = '\0';
3257 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003258 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003259 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003260 if (*nw)
3261 *nw++ = '\0';
3262 type = stktable_get_data_type(cw);
3263 if (type < 0) {
3264 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3265 file, linenum, args[0], cw);
3266 err_code |= ERR_ALERT | ERR_FATAL;
3267 goto out;
3268 }
Willy Tarreauac782882010-06-20 10:41:54 +02003269
3270 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3271 switch (err) {
3272 case PE_NONE: break;
3273 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003274 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3275 file, linenum, args[0], cw);
3276 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003277 break;
3278
3279 case PE_ARG_MISSING:
3280 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3281 file, linenum, args[0], cw);
3282 err_code |= ERR_ALERT | ERR_FATAL;
3283 goto out;
3284
3285 case PE_ARG_NOT_USED:
3286 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3287 file, linenum, args[0], cw);
3288 err_code |= ERR_ALERT | ERR_FATAL;
3289 goto out;
3290
3291 default:
3292 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3293 file, linenum, args[0], cw);
3294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003296 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003297 }
3298 myidx++;
3299 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003300 else {
3301 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3302 file, linenum, args[myidx]);
3303 err_code |= ERR_ALERT | ERR_FATAL;
3304 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003305 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003306 }
3307
3308 if (!curproxy->table.size) {
3309 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3310 file, linenum);
3311 err_code |= ERR_ALERT | ERR_FATAL;
3312 goto out;
3313 }
3314
3315 if (curproxy->table.type == (unsigned int)-1) {
3316 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3317 file, linenum);
3318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
3320 }
3321 }
3322 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003323 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003324 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003325 int myidx = 0;
3326 const char *name = NULL;
3327 int flags;
3328
3329 if (curproxy == &defproxy) {
3330 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3331 err_code |= ERR_ALERT | ERR_FATAL;
3332 goto out;
3333 }
3334
3335 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3336 err_code |= ERR_WARN;
3337 goto out;
3338 }
3339
3340 myidx++;
3341 if ((strcmp(args[myidx], "store") == 0) ||
3342 (strcmp(args[myidx], "store-request") == 0)) {
3343 myidx++;
3344 flags = STK_IS_STORE;
3345 }
3346 else if (strcmp(args[myidx], "store-response") == 0) {
3347 myidx++;
3348 flags = STK_IS_STORE | STK_ON_RSP;
3349 }
3350 else if (strcmp(args[myidx], "match") == 0) {
3351 myidx++;
3352 flags = STK_IS_MATCH;
3353 }
3354 else if (strcmp(args[myidx], "on") == 0) {
3355 myidx++;
3356 flags = STK_IS_MATCH | STK_IS_STORE;
3357 }
3358 else {
3359 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3360 err_code |= ERR_ALERT | ERR_FATAL;
3361 goto out;
3362 }
3363
3364 if (*(args[myidx]) == 0) {
3365 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3366 err_code |= ERR_ALERT | ERR_FATAL;
3367 goto out;
3368 }
3369
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003370 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003371 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003372 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003373 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003374 err_code |= ERR_ALERT | ERR_FATAL;
3375 goto out;
3376 }
3377
3378 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003379 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3380 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3381 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003382 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003383 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003384 goto out;
3385 }
3386 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003387 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3388 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3389 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003390 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003391 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003392 goto out;
3393 }
3394 }
3395
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003396 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003397 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003398
Emeric Brunb982a3d2010-01-04 15:45:53 +01003399 if (strcmp(args[myidx], "table") == 0) {
3400 myidx++;
3401 name = args[myidx++];
3402 }
3403
Willy Tarreauef6494c2010-01-28 17:12:36 +01003404 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003405 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3406 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3407 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003408 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003409 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003410 goto out;
3411 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003412 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003413 else if (*(args[myidx])) {
3414 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3415 file, linenum, args[0], args[myidx]);
3416 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003417 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003418 goto out;
3419 }
Emeric Brun97679e72010-09-23 17:56:44 +02003420 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003421 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003422 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003423 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003424
Emeric Brunb982a3d2010-01-04 15:45:53 +01003425 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3426 rule->cond = cond;
3427 rule->expr = expr;
3428 rule->flags = flags;
3429 rule->table.name = name ? strdup(name) : NULL;
3430 LIST_INIT(&rule->list);
3431 if (flags & STK_ON_RSP)
3432 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3433 else
3434 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3435 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003436 else if (!strcmp(args[0], "stats")) {
3437 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3438 curproxy->uri_auth = NULL; /* we must detach from the default config */
3439
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003440 if (!*args[1]) {
3441 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003442 } else if (!strcmp(args[1], "admin")) {
3443 struct stats_admin_rule *rule;
3444
3445 if (curproxy == &defproxy) {
3446 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3447 err_code |= ERR_ALERT | ERR_FATAL;
3448 goto out;
3449 }
3450
3451 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3452 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3453 err_code |= ERR_ALERT | ERR_ABORT;
3454 goto out;
3455 }
3456
3457 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3458 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3459 file, linenum, args[0], args[1]);
3460 err_code |= ERR_ALERT | ERR_FATAL;
3461 goto out;
3462 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003463 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3464 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3465 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003466 err_code |= ERR_ALERT | ERR_FATAL;
3467 goto out;
3468 }
3469
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003470 err_code |= warnif_cond_conflicts(cond,
3471 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3472 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003473
3474 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3475 rule->cond = cond;
3476 LIST_INIT(&rule->list);
3477 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003478 } else if (!strcmp(args[1], "uri")) {
3479 if (*(args[2]) == 0) {
3480 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003481 err_code |= ERR_ALERT | ERR_FATAL;
3482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003483 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3484 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003485 err_code |= ERR_ALERT | ERR_ABORT;
3486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003487 }
3488 } else if (!strcmp(args[1], "realm")) {
3489 if (*(args[2]) == 0) {
3490 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003491 err_code |= ERR_ALERT | ERR_FATAL;
3492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003493 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3494 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003495 err_code |= ERR_ALERT | ERR_ABORT;
3496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003497 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003498 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003499 unsigned interval;
3500
3501 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3502 if (err) {
3503 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3504 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003505 err_code |= ERR_ALERT | ERR_FATAL;
3506 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003507 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3508 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003509 err_code |= ERR_ALERT | ERR_ABORT;
3510 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003511 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003512 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003513 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003514
3515 if (curproxy == &defproxy) {
3516 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3517 err_code |= ERR_ALERT | ERR_FATAL;
3518 goto out;
3519 }
3520
3521 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3522 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3523 err_code |= ERR_ALERT | ERR_ABORT;
3524 goto out;
3525 }
3526
Willy Tarreauff011f22011-01-06 17:51:27 +01003527 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3528 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003529 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3530 file, linenum, args[0]);
3531 err_code |= ERR_WARN;
3532 }
3533
Willy Tarreauff011f22011-01-06 17:51:27 +01003534 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003535
Willy Tarreauff011f22011-01-06 17:51:27 +01003536 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003537 err_code |= ERR_ALERT | ERR_ABORT;
3538 goto out;
3539 }
3540
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003541 err_code |= warnif_cond_conflicts(rule->cond,
3542 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3543 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003544 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003545
Willy Tarreaubaaee002006-06-26 02:48:02 +02003546 } else if (!strcmp(args[1], "auth")) {
3547 if (*(args[2]) == 0) {
3548 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003549 err_code |= ERR_ALERT | ERR_FATAL;
3550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003551 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3552 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_ALERT | ERR_ABORT;
3554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003555 }
3556 } else if (!strcmp(args[1], "scope")) {
3557 if (*(args[2]) == 0) {
3558 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003559 err_code |= ERR_ALERT | ERR_FATAL;
3560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003561 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3562 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003563 err_code |= ERR_ALERT | ERR_ABORT;
3564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003565 }
3566 } else if (!strcmp(args[1], "enable")) {
3567 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3568 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003569 err_code |= ERR_ALERT | ERR_ABORT;
3570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003571 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003572 } else if (!strcmp(args[1], "hide-version")) {
3573 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3574 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003575 err_code |= ERR_ALERT | ERR_ABORT;
3576 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003577 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003578 } else if (!strcmp(args[1], "show-legends")) {
3579 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3580 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3581 err_code |= ERR_ALERT | ERR_ABORT;
3582 goto out;
3583 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003584 } else if (!strcmp(args[1], "show-node")) {
3585
3586 if (*args[2]) {
3587 int i;
3588 char c;
3589
3590 for (i=0; args[2][i]; i++) {
3591 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003592 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3593 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003594 break;
3595 }
3596
3597 if (!i || args[2][i]) {
3598 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3599 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3600 file, linenum, args[0], args[1]);
3601 err_code |= ERR_ALERT | ERR_FATAL;
3602 goto out;
3603 }
3604 }
3605
3606 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3607 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3608 err_code |= ERR_ALERT | ERR_ABORT;
3609 goto out;
3610 }
3611 } else if (!strcmp(args[1], "show-desc")) {
3612 char *desc = NULL;
3613
3614 if (*args[2]) {
3615 int i, len=0;
3616 char *d;
3617
Willy Tarreau348acfe2014-04-14 15:00:39 +02003618 for (i = 2; *args[i]; i++)
3619 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003620
3621 desc = d = (char *)calloc(1, len);
3622
Willy Tarreau348acfe2014-04-14 15:00:39 +02003623 d += snprintf(d, desc + len - d, "%s", args[2]);
3624 for (i = 3; *args[i]; i++)
3625 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003626 }
3627
3628 if (!*args[2] && !global.desc)
3629 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3630 file, linenum, args[1]);
3631 else {
3632 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3633 free(desc);
3634 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3635 err_code |= ERR_ALERT | ERR_ABORT;
3636 goto out;
3637 }
3638 free(desc);
3639 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003640 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003641stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003642 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 +01003643 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003644 err_code |= ERR_ALERT | ERR_FATAL;
3645 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003646 }
3647 }
3648 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003649 int optnum;
3650
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003651 if (*(args[1]) == '\0') {
3652 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3653 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003654 err_code |= ERR_ALERT | ERR_FATAL;
3655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003657
3658 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3659 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003660 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3661 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3662 file, linenum, cfg_opts[optnum].name);
3663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
3665 }
Willy Tarreau93893792009-07-23 13:19:11 +02003666 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3667 err_code |= ERR_WARN;
3668 goto out;
3669 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003670
Willy Tarreau3842f002009-06-14 11:39:52 +02003671 curproxy->no_options &= ~cfg_opts[optnum].val;
3672 curproxy->options &= ~cfg_opts[optnum].val;
3673
3674 switch (kwm) {
3675 case KWM_STD:
3676 curproxy->options |= cfg_opts[optnum].val;
3677 break;
3678 case KWM_NO:
3679 curproxy->no_options |= cfg_opts[optnum].val;
3680 break;
3681 case KWM_DEF: /* already cleared */
3682 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003683 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003684
Willy Tarreau93893792009-07-23 13:19:11 +02003685 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003686 }
3687 }
3688
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003689 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3690 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003691 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3692 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3693 file, linenum, cfg_opts2[optnum].name);
3694 err_code |= ERR_ALERT | ERR_FATAL;
3695 goto out;
3696 }
Willy Tarreau93893792009-07-23 13:19:11 +02003697 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3698 err_code |= ERR_WARN;
3699 goto out;
3700 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003701
Willy Tarreau3842f002009-06-14 11:39:52 +02003702 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3703 curproxy->options2 &= ~cfg_opts2[optnum].val;
3704
3705 switch (kwm) {
3706 case KWM_STD:
3707 curproxy->options2 |= cfg_opts2[optnum].val;
3708 break;
3709 case KWM_NO:
3710 curproxy->no_options2 |= cfg_opts2[optnum].val;
3711 break;
3712 case KWM_DEF: /* already cleared */
3713 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003714 }
Willy Tarreau93893792009-07-23 13:19:11 +02003715 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003716 }
3717 }
3718
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003719 /* HTTP options override each other. They can be cancelled using
3720 * "no option xxx" which only switches to default mode if the mode
3721 * was this one (useful for cancelling options set in defaults
3722 * sections).
3723 */
3724 if (strcmp(args[1], "httpclose") == 0) {
3725 if (kwm == KWM_STD) {
3726 curproxy->options &= ~PR_O_HTTP_MODE;
3727 curproxy->options |= PR_O_HTTP_PCL;
3728 goto out;
3729 }
3730 else if (kwm == KWM_NO) {
3731 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3732 curproxy->options &= ~PR_O_HTTP_MODE;
3733 goto out;
3734 }
3735 }
3736 else if (strcmp(args[1], "forceclose") == 0) {
3737 if (kwm == KWM_STD) {
3738 curproxy->options &= ~PR_O_HTTP_MODE;
3739 curproxy->options |= PR_O_HTTP_FCL;
3740 goto out;
3741 }
3742 else if (kwm == KWM_NO) {
3743 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3744 curproxy->options &= ~PR_O_HTTP_MODE;
3745 goto out;
3746 }
3747 }
3748 else if (strcmp(args[1], "http-server-close") == 0) {
3749 if (kwm == KWM_STD) {
3750 curproxy->options &= ~PR_O_HTTP_MODE;
3751 curproxy->options |= PR_O_HTTP_SCL;
3752 goto out;
3753 }
3754 else if (kwm == KWM_NO) {
3755 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3756 curproxy->options &= ~PR_O_HTTP_MODE;
3757 goto out;
3758 }
3759 }
3760 else if (strcmp(args[1], "http-keep-alive") == 0) {
3761 if (kwm == KWM_STD) {
3762 curproxy->options &= ~PR_O_HTTP_MODE;
3763 curproxy->options |= PR_O_HTTP_KAL;
3764 goto out;
3765 }
3766 else if (kwm == KWM_NO) {
3767 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3768 curproxy->options &= ~PR_O_HTTP_MODE;
3769 goto out;
3770 }
3771 }
3772 else if (strcmp(args[1], "http-tunnel") == 0) {
3773 if (kwm == KWM_STD) {
3774 curproxy->options &= ~PR_O_HTTP_MODE;
3775 curproxy->options |= PR_O_HTTP_TUN;
3776 goto out;
3777 }
3778 else if (kwm == KWM_NO) {
3779 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3780 curproxy->options &= ~PR_O_HTTP_MODE;
3781 goto out;
3782 }
3783 }
3784
Willy Tarreau3842f002009-06-14 11:39:52 +02003785 if (kwm != KWM_STD) {
3786 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003787 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_ALERT | ERR_FATAL;
3789 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003790 }
3791
Emeric Brun3a058f32009-06-30 18:26:00 +02003792 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003793 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003794 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003795 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003796 if (*(args[2]) != '\0') {
3797 if (!strcmp(args[2], "clf")) {
3798 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003799 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003800 } else {
William Lallemand629b1c02015-05-28 18:02:48 +02003801 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003802 err_code |= ERR_ALERT | ERR_FATAL;
3803 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003804 }
3805 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003806 if (curproxy->conf.logformat_string != default_http_log_format &&
3807 curproxy->conf.logformat_string != default_tcp_log_format &&
3808 curproxy->conf.logformat_string != clf_http_log_format)
3809 free(curproxy->conf.logformat_string);
3810 curproxy->conf.logformat_string = logformat;
3811
3812 free(curproxy->conf.lfs_file);
3813 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3814 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003815 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003816 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003817 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003818 if (curproxy->conf.logformat_string != default_http_log_format &&
3819 curproxy->conf.logformat_string != default_tcp_log_format &&
3820 curproxy->conf.logformat_string != clf_http_log_format)
3821 free(curproxy->conf.logformat_string);
3822 curproxy->conf.logformat_string = default_tcp_log_format;
3823
3824 free(curproxy->conf.lfs_file);
3825 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3826 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003827 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003828 else if (!strcmp(args[1], "tcpka")) {
3829 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003830 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003831 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003832
3833 if (curproxy->cap & PR_CAP_FE)
3834 curproxy->options |= PR_O_TCP_CLI_KA;
3835 if (curproxy->cap & PR_CAP_BE)
3836 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003837 }
3838 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003839 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_WARN;
3841
Willy Tarreaubaaee002006-06-26 02:48:02 +02003842 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003843 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003844 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003845 curproxy->options2 &= ~PR_O2_CHK_ANY;
3846 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003847 if (!*args[2]) { /* no argument */
3848 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3849 curproxy->check_len = strlen(DEF_CHECK_REQ);
3850 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003851 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852 curproxy->check_req = (char *)malloc(reqlen);
3853 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003854 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003855 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003856 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003857 if (*args[4])
3858 reqlen += strlen(args[4]);
3859 else
3860 reqlen += strlen("HTTP/1.0");
3861
3862 curproxy->check_req = (char *)malloc(reqlen);
3863 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003864 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003865 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003866 }
3867 else if (!strcmp(args[1], "ssl-hello-chk")) {
3868 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003869 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003870 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003871
Willy Tarreaua534fea2008-08-03 12:19:50 +02003872 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003873 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003874 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003875 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003876 }
Willy Tarreau23677902007-05-08 23:50:35 +02003877 else if (!strcmp(args[1], "smtpchk")) {
3878 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003879 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003880 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003881 curproxy->options2 &= ~PR_O2_CHK_ANY;
3882 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003883
3884 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3885 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3886 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3887 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3888 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3889 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3890 curproxy->check_req = (char *)malloc(reqlen);
3891 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3892 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3893 } else {
3894 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3895 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3896 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3897 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3898 }
3899 }
3900 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003901 else if (!strcmp(args[1], "pgsql-check")) {
3902 /* use PostgreSQL request to check servers' health */
3903 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3904 err_code |= ERR_WARN;
3905
3906 free(curproxy->check_req);
3907 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003908 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003909 curproxy->options2 |= PR_O2_PGSQL_CHK;
3910
3911 if (*(args[2])) {
3912 int cur_arg = 2;
3913
3914 while (*(args[cur_arg])) {
3915 if (strcmp(args[cur_arg], "user") == 0) {
3916 char * packet;
3917 uint32_t packet_len;
3918 uint32_t pv;
3919
3920 /* suboption header - needs additional argument for it */
3921 if (*(args[cur_arg+1]) == 0) {
3922 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3923 file, linenum, args[0], args[1], args[cur_arg]);
3924 err_code |= ERR_ALERT | ERR_FATAL;
3925 goto out;
3926 }
3927
3928 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3929 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3930 pv = htonl(0x30000); /* protocol version 3.0 */
3931
3932 packet = (char*) calloc(1, packet_len);
3933
3934 memcpy(packet + 4, &pv, 4);
3935
3936 /* copy "user" */
3937 memcpy(packet + 8, "user", 4);
3938
3939 /* copy username */
3940 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3941
3942 free(curproxy->check_req);
3943 curproxy->check_req = packet;
3944 curproxy->check_len = packet_len;
3945
3946 packet_len = htonl(packet_len);
3947 memcpy(packet, &packet_len, 4);
3948 cur_arg += 2;
3949 } else {
3950 /* unknown suboption - catchall */
3951 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3952 file, linenum, args[0], args[1]);
3953 err_code |= ERR_ALERT | ERR_FATAL;
3954 goto out;
3955 }
3956 } /* end while loop */
3957 }
3958 }
3959
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003960 else if (!strcmp(args[1], "redis-check")) {
3961 /* use REDIS PING request to check servers' health */
3962 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3963 err_code |= ERR_WARN;
3964
3965 free(curproxy->check_req);
3966 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003967 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003968 curproxy->options2 |= PR_O2_REDIS_CHK;
3969
3970 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3971 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3972 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3973 }
3974
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003975 else if (!strcmp(args[1], "mysql-check")) {
3976 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003977 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3978 err_code |= ERR_WARN;
3979
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003980 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003981 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003982 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003983 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003984
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003985 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003986 * const char mysql40_client_auth_pkt[] = {
3987 * "\x0e\x00\x00" // packet length
3988 * "\x01" // packet number
3989 * "\x00\x00" // client capabilities
3990 * "\x00\x00\x01" // max packet
3991 * "haproxy\x00" // username (null terminated string)
3992 * "\x00" // filler (always 0x00)
3993 * "\x01\x00\x00" // packet length
3994 * "\x00" // packet number
3995 * "\x01" // COM_QUIT command
3996 * };
3997 */
3998
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003999 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4000 * const char mysql41_client_auth_pkt[] = {
4001 * "\x0e\x00\x00\" // packet length
4002 * "\x01" // packet number
4003 * "\x00\x00\x00\x00" // client capabilities
4004 * "\x00\x00\x00\x01" // max packet
4005 * "\x21" // character set (UTF-8)
4006 * char[23] // All zeroes
4007 * "haproxy\x00" // username (null terminated string)
4008 * "\x00" // filler (always 0x00)
4009 * "\x01\x00\x00" // packet length
4010 * "\x00" // packet number
4011 * "\x01" // COM_QUIT command
4012 * };
4013 */
4014
4015
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004016 if (*(args[2])) {
4017 int cur_arg = 2;
4018
4019 while (*(args[cur_arg])) {
4020 if (strcmp(args[cur_arg], "user") == 0) {
4021 char *mysqluser;
4022 int packetlen, reqlen, userlen;
4023
4024 /* suboption header - needs additional argument for it */
4025 if (*(args[cur_arg+1]) == 0) {
4026 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4027 file, linenum, args[0], args[1], args[cur_arg]);
4028 err_code |= ERR_ALERT | ERR_FATAL;
4029 goto out;
4030 }
4031 mysqluser = args[cur_arg + 1];
4032 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004033
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004034 if (*(args[cur_arg+2])) {
4035 if (!strcmp(args[cur_arg+2], "post-41")) {
4036 packetlen = userlen + 7 + 27;
4037 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004038
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004039 free(curproxy->check_req);
4040 curproxy->check_req = (char *)calloc(1, reqlen);
4041 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004042
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004043 snprintf(curproxy->check_req, 4, "%c%c%c",
4044 ((unsigned char) packetlen & 0xff),
4045 ((unsigned char) (packetlen >> 8) & 0xff),
4046 ((unsigned char) (packetlen >> 16) & 0xff));
4047
4048 curproxy->check_req[3] = 1;
4049 curproxy->check_req[5] = 130;
4050 curproxy->check_req[11] = 1;
4051 curproxy->check_req[12] = 33;
4052 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4053 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4054 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4055 cur_arg += 3;
4056 } else {
4057 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4058 err_code |= ERR_ALERT | ERR_FATAL;
4059 goto out;
4060 }
4061 } else {
4062 packetlen = userlen + 7;
4063 reqlen = packetlen + 9;
4064
4065 free(curproxy->check_req);
4066 curproxy->check_req = (char *)calloc(1, reqlen);
4067 curproxy->check_len = reqlen;
4068
4069 snprintf(curproxy->check_req, 4, "%c%c%c",
4070 ((unsigned char) packetlen & 0xff),
4071 ((unsigned char) (packetlen >> 8) & 0xff),
4072 ((unsigned char) (packetlen >> 16) & 0xff));
4073
4074 curproxy->check_req[3] = 1;
4075 curproxy->check_req[5] = 128;
4076 curproxy->check_req[8] = 1;
4077 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4078 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4079 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4080 cur_arg += 2;
4081 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004082 } else {
4083 /* unknown suboption - catchall */
4084 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4085 file, linenum, args[0], args[1]);
4086 err_code |= ERR_ALERT | ERR_FATAL;
4087 goto out;
4088 }
4089 } /* end while loop */
4090 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004091 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004092 else if (!strcmp(args[1], "ldap-check")) {
4093 /* use LDAP request to check servers' health */
4094 free(curproxy->check_req);
4095 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004096 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004097 curproxy->options2 |= PR_O2_LDAP_CHK;
4098
4099 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4100 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4101 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4102 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004103 else if (!strcmp(args[1], "tcp-check")) {
4104 /* use raw TCPCHK send/expect to check servers' health */
4105 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4106 err_code |= ERR_WARN;
4107
4108 free(curproxy->check_req);
4109 curproxy->check_req = NULL;
4110 curproxy->options2 &= ~PR_O2_CHK_ANY;
4111 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4112 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004113 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004114 int cur_arg;
4115
4116 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4117 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004118 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004119
Willy Tarreau87cf5142011-08-19 22:57:24 +02004120 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004121
4122 free(curproxy->fwdfor_hdr_name);
4123 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4124 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4125
4126 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4127 cur_arg = 2;
4128 while (*(args[cur_arg])) {
4129 if (!strcmp(args[cur_arg], "except")) {
4130 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004131 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004132 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4133 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004136 }
4137 /* flush useless bits */
4138 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004139 cur_arg += 2;
4140 } else if (!strcmp(args[cur_arg], "header")) {
4141 /* suboption header - needs additional argument for it */
4142 if (*(args[cur_arg+1]) == 0) {
4143 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4144 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004145 err_code |= ERR_ALERT | ERR_FATAL;
4146 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004147 }
4148 free(curproxy->fwdfor_hdr_name);
4149 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4150 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4151 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004152 } else if (!strcmp(args[cur_arg], "if-none")) {
4153 curproxy->options &= ~PR_O_FF_ALWAYS;
4154 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004155 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004156 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004157 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004158 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004159 err_code |= ERR_ALERT | ERR_FATAL;
4160 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004161 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004162 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004163 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004164 else if (!strcmp(args[1], "originalto")) {
4165 int cur_arg;
4166
4167 /* insert x-original-to field, but not for the IP address listed as an except.
4168 * set default options (ie: bitfield, header name, etc)
4169 */
4170
4171 curproxy->options |= PR_O_ORGTO;
4172
4173 free(curproxy->orgto_hdr_name);
4174 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4175 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4176
Willy Tarreau87cf5142011-08-19 22:57:24 +02004177 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004178 cur_arg = 2;
4179 while (*(args[cur_arg])) {
4180 if (!strcmp(args[cur_arg], "except")) {
4181 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004182 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 +02004183 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4184 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004187 }
4188 /* flush useless bits */
4189 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4190 cur_arg += 2;
4191 } else if (!strcmp(args[cur_arg], "header")) {
4192 /* suboption header - needs additional argument for it */
4193 if (*(args[cur_arg+1]) == 0) {
4194 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4195 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004196 err_code |= ERR_ALERT | ERR_FATAL;
4197 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004198 }
4199 free(curproxy->orgto_hdr_name);
4200 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4201 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4202 cur_arg += 2;
4203 } else {
4204 /* unknown suboption - catchall */
4205 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4206 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004207 err_code |= ERR_ALERT | ERR_FATAL;
4208 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004209 }
4210 } /* end while loop */
4211 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004212 else {
4213 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004216 }
Willy Tarreau93893792009-07-23 13:19:11 +02004217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004218 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004219 else if (!strcmp(args[0], "default_backend")) {
4220 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004221 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004222
4223 if (*(args[1]) == 0) {
4224 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004225 err_code |= ERR_ALERT | ERR_FATAL;
4226 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004227 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004228 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004229 curproxy->defbe.name = strdup(args[1]);
4230 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004231 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004232 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004233 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004234
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004235 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4236 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 +01004237 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004238 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004239 /* enable reconnections to dispatch */
4240 curproxy->options |= PR_O_REDISP;
4241 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004242 else if (!strcmp(args[0], "http-check")) {
4243 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004244 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004245
4246 if (strcmp(args[1], "disable-on-404") == 0) {
4247 /* enable a graceful server shutdown on an HTTP 404 response */
4248 curproxy->options |= PR_O_DISABLE404;
4249 }
Willy Tarreauef781042010-01-27 11:53:01 +01004250 else if (strcmp(args[1], "send-state") == 0) {
4251 /* enable emission of the apparent state of a server in HTTP checks */
4252 curproxy->options2 |= PR_O2_CHK_SNDST;
4253 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004254 else if (strcmp(args[1], "expect") == 0) {
4255 const char *ptr_arg;
4256 int cur_arg;
4257
4258 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4259 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4260 err_code |= ERR_ALERT | ERR_FATAL;
4261 goto out;
4262 }
4263
4264 cur_arg = 2;
4265 /* consider exclamation marks, sole or at the beginning of a word */
4266 while (*(ptr_arg = args[cur_arg])) {
4267 while (*ptr_arg == '!') {
4268 curproxy->options2 ^= PR_O2_EXP_INV;
4269 ptr_arg++;
4270 }
4271 if (*ptr_arg)
4272 break;
4273 cur_arg++;
4274 }
4275 /* now ptr_arg points to the beginning of a word past any possible
4276 * exclamation mark, and cur_arg is the argument which holds this word.
4277 */
4278 if (strcmp(ptr_arg, "status") == 0) {
4279 if (!*(args[cur_arg + 1])) {
4280 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4281 file, linenum, args[0], args[1], ptr_arg);
4282 err_code |= ERR_ALERT | ERR_FATAL;
4283 goto out;
4284 }
4285 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004286 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004287 curproxy->expect_str = strdup(args[cur_arg + 1]);
4288 }
4289 else if (strcmp(ptr_arg, "string") == 0) {
4290 if (!*(args[cur_arg + 1])) {
4291 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4292 file, linenum, args[0], args[1], ptr_arg);
4293 err_code |= ERR_ALERT | ERR_FATAL;
4294 goto out;
4295 }
4296 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004297 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004298 curproxy->expect_str = strdup(args[cur_arg + 1]);
4299 }
4300 else if (strcmp(ptr_arg, "rstatus") == 0) {
4301 if (!*(args[cur_arg + 1])) {
4302 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4303 file, linenum, args[0], args[1], ptr_arg);
4304 err_code |= ERR_ALERT | ERR_FATAL;
4305 goto out;
4306 }
4307 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004308 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004309 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004310 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004311 free(curproxy->expect_regex);
4312 curproxy->expect_regex = NULL;
4313 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004314 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004315 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4316 error = NULL;
4317 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4318 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4319 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4320 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004321 err_code |= ERR_ALERT | ERR_FATAL;
4322 goto out;
4323 }
4324 }
4325 else if (strcmp(ptr_arg, "rstring") == 0) {
4326 if (!*(args[cur_arg + 1])) {
4327 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4328 file, linenum, args[0], args[1], ptr_arg);
4329 err_code |= ERR_ALERT | ERR_FATAL;
4330 goto out;
4331 }
4332 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004333 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004334 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004335 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004336 free(curproxy->expect_regex);
4337 curproxy->expect_regex = NULL;
4338 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004339 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004340 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4341 error = NULL;
4342 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4343 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4344 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4345 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004346 err_code |= ERR_ALERT | ERR_FATAL;
4347 goto out;
4348 }
4349 }
4350 else {
4351 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4352 file, linenum, args[0], args[1], ptr_arg);
4353 err_code |= ERR_ALERT | ERR_FATAL;
4354 goto out;
4355 }
4356 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004357 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004358 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 +02004359 err_code |= ERR_ALERT | ERR_FATAL;
4360 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004361 }
4362 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004363 else if (!strcmp(args[0], "tcp-check")) {
4364 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4365 err_code |= ERR_WARN;
4366
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004367 if (strcmp(args[1], "connect") == 0) {
4368 const char *ptr_arg;
4369 int cur_arg;
4370 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004371
4372 /* check if first rule is also a 'connect' action */
Willy Tarreau5bff0592015-05-13 12:24:53 +02004373 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
Willy Tarreau97fccc82015-05-13 12:08:21 +02004374
Willy Tarreau5bff0592015-05-13 12:24:53 +02004375 if (&tcpcheck->list != &curproxy->tcpcheck_rules
4376 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4377 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4378 file, linenum);
4379 err_code |= ERR_ALERT | ERR_FATAL;
4380 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004381 }
4382
4383 cur_arg = 2;
4384 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4385 tcpcheck->action = TCPCHK_ACT_CONNECT;
4386
4387 /* parsing each parameters to fill up the rule */
4388 while (*(ptr_arg = args[cur_arg])) {
4389 /* tcp port */
4390 if (strcmp(args[cur_arg], "port") == 0) {
4391 if ( (atol(args[cur_arg + 1]) > 65535) ||
4392 (atol(args[cur_arg + 1]) < 1) ){
4393 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4394 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4395 err_code |= ERR_ALERT | ERR_FATAL;
4396 goto out;
4397 }
4398 tcpcheck->port = atol(args[cur_arg + 1]);
4399 cur_arg += 2;
4400 }
4401 /* send proxy protocol */
4402 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4403 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4404 cur_arg++;
4405 }
4406#ifdef USE_OPENSSL
4407 else if (strcmp(args[cur_arg], "ssl") == 0) {
4408 curproxy->options |= PR_O_TCPCHK_SSL;
4409 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4410 cur_arg++;
4411 }
4412#endif /* USE_OPENSSL */
4413 else {
4414#ifdef USE_OPENSSL
4415 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4416#else /* USE_OPENSSL */
4417 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4418#endif /* USE_OPENSSL */
4419 file, linenum, args[0], args[1], args[cur_arg]);
4420 err_code |= ERR_ALERT | ERR_FATAL;
4421 goto out;
4422 }
4423
4424 }
4425
4426 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4427 }
4428 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004429 if (! *(args[2]) ) {
4430 /* SEND string expected */
4431 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4432 file, linenum, args[0], args[1], args[2]);
4433 err_code |= ERR_ALERT | ERR_FATAL;
4434 goto out;
4435 } else {
4436 struct tcpcheck_rule *tcpcheck;
4437
4438 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4439
4440 tcpcheck->action = TCPCHK_ACT_SEND;
4441 tcpcheck->string_len = strlen(args[2]);
4442 tcpcheck->string = strdup(args[2]);
4443 tcpcheck->expect_regex = NULL;
4444
4445 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4446 }
4447 }
4448 else if (strcmp(args[1], "send-binary") == 0) {
4449 if (! *(args[2]) ) {
4450 /* SEND binary string expected */
4451 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4452 file, linenum, args[0], args[1], args[2]);
4453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
4455 } else {
4456 struct tcpcheck_rule *tcpcheck;
4457 char *err = NULL;
4458
4459 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4460
4461 tcpcheck->action = TCPCHK_ACT_SEND;
4462 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4463 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4464 file, linenum, args[0], args[1], args[2], err);
4465 err_code |= ERR_ALERT | ERR_FATAL;
4466 goto out;
4467 }
4468 tcpcheck->expect_regex = NULL;
4469
4470 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4471 }
4472 }
4473 else if (strcmp(args[1], "expect") == 0) {
4474 const char *ptr_arg;
4475 int cur_arg;
4476 int inverse = 0;
4477
4478 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4479 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4480 err_code |= ERR_ALERT | ERR_FATAL;
4481 goto out;
4482 }
4483
4484 cur_arg = 2;
4485 /* consider exclamation marks, sole or at the beginning of a word */
4486 while (*(ptr_arg = args[cur_arg])) {
4487 while (*ptr_arg == '!') {
4488 inverse = !inverse;
4489 ptr_arg++;
4490 }
4491 if (*ptr_arg)
4492 break;
4493 cur_arg++;
4494 }
4495 /* now ptr_arg points to the beginning of a word past any possible
4496 * exclamation mark, and cur_arg is the argument which holds this word.
4497 */
4498 if (strcmp(ptr_arg, "binary") == 0) {
4499 if (!*(args[cur_arg + 1])) {
4500 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4501 file, linenum, args[0], args[1], ptr_arg);
4502 err_code |= ERR_ALERT | ERR_FATAL;
4503 goto out;
4504 }
4505 struct tcpcheck_rule *tcpcheck;
4506 char *err = NULL;
4507
4508 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4509
4510 tcpcheck->action = TCPCHK_ACT_EXPECT;
4511 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4512 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4513 file, linenum, args[0], args[1], args[2], err);
4514 err_code |= ERR_ALERT | ERR_FATAL;
4515 goto out;
4516 }
4517 tcpcheck->expect_regex = NULL;
4518 tcpcheck->inverse = inverse;
4519
4520 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4521 }
4522 else if (strcmp(ptr_arg, "string") == 0) {
4523 if (!*(args[cur_arg + 1])) {
4524 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4525 file, linenum, args[0], args[1], ptr_arg);
4526 err_code |= ERR_ALERT | ERR_FATAL;
4527 goto out;
4528 }
4529 struct tcpcheck_rule *tcpcheck;
4530
4531 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4532
4533 tcpcheck->action = TCPCHK_ACT_EXPECT;
4534 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4535 tcpcheck->string = strdup(args[cur_arg + 1]);
4536 tcpcheck->expect_regex = NULL;
4537 tcpcheck->inverse = inverse;
4538
4539 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4540 }
4541 else if (strcmp(ptr_arg, "rstring") == 0) {
4542 if (!*(args[cur_arg + 1])) {
4543 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4544 file, linenum, args[0], args[1], ptr_arg);
4545 err_code |= ERR_ALERT | ERR_FATAL;
4546 goto out;
4547 }
4548 struct tcpcheck_rule *tcpcheck;
4549
4550 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4551
4552 tcpcheck->action = TCPCHK_ACT_EXPECT;
4553 tcpcheck->string_len = 0;
4554 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004555 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4556 error = NULL;
4557 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4558 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4559 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4560 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004561 err_code |= ERR_ALERT | ERR_FATAL;
4562 goto out;
4563 }
4564 tcpcheck->inverse = inverse;
4565
4566 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4567 }
4568 else {
4569 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4570 file, linenum, args[0], args[1], ptr_arg);
4571 err_code |= ERR_ALERT | ERR_FATAL;
4572 goto out;
4573 }
4574 }
4575 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004576 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004577 err_code |= ERR_ALERT | ERR_FATAL;
4578 goto out;
4579 }
4580 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004581 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004582 if (curproxy == &defproxy) {
4583 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004584 err_code |= ERR_ALERT | ERR_FATAL;
4585 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004586 }
4587
Willy Tarreaub80c2302007-11-30 20:51:32 +01004588 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004589 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004590
4591 if (strcmp(args[1], "fail") == 0) {
4592 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004593 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004594 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4595 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004596 err_code |= ERR_ALERT | ERR_FATAL;
4597 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004598 }
4599
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004600 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4601 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4602 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004603 err_code |= ERR_ALERT | ERR_FATAL;
4604 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004605 }
4606 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4607 }
4608 else {
4609 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004612 }
4613 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004614#ifdef TPROXY
4615 else if (!strcmp(args[0], "transparent")) {
4616 /* enable transparent proxy connections */
4617 curproxy->options |= PR_O_TRANSP;
4618 }
4619#endif
4620 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004621 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004622 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004623
Willy Tarreaubaaee002006-06-26 02:48:02 +02004624 if (*(args[1]) == 0) {
4625 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004626 err_code |= ERR_ALERT | ERR_FATAL;
4627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004628 }
4629 curproxy->maxconn = atol(args[1]);
4630 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004631 else if (!strcmp(args[0], "backlog")) { /* backlog */
4632 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004633 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004634
4635 if (*(args[1]) == 0) {
4636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004639 }
4640 curproxy->backlog = atol(args[1]);
4641 }
Willy Tarreau86034312006-12-29 00:10:33 +01004642 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004643 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004644 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004645
Willy Tarreau86034312006-12-29 00:10:33 +01004646 if (*(args[1]) == 0) {
4647 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004648 err_code |= ERR_ALERT | ERR_FATAL;
4649 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004650 }
4651 curproxy->fullconn = atol(args[1]);
4652 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004653 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4654 if (*(args[1]) == 0) {
4655 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004656 err_code |= ERR_ALERT | ERR_FATAL;
4657 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004658 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004659 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4660 if (err) {
4661 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4662 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004663 err_code |= ERR_ALERT | ERR_FATAL;
4664 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004665 }
4666 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004667 }
4668 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004669 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004670 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004671 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004672
Willy Tarreaubaaee002006-06-26 02:48:02 +02004673 if (curproxy == &defproxy) {
4674 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004675 err_code |= ERR_ALERT | ERR_FATAL;
4676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004677 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004678 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004679 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004680
Willy Tarreau902636f2013-03-10 19:44:48 +01004681 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004682 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004683 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004684 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004685 goto out;
4686 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004687
4688 proto = protocol_by_family(sk->ss_family);
4689 if (!proto || !proto->connect) {
4690 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4691 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004692 err_code |= ERR_ALERT | ERR_FATAL;
4693 goto out;
4694 }
4695
4696 if (port1 != port2) {
4697 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4698 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004699 err_code |= ERR_ALERT | ERR_FATAL;
4700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004701 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004702
4703 if (!port1) {
4704 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4705 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004706 err_code |= ERR_ALERT | ERR_FATAL;
4707 goto out;
4708 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004709
Willy Tarreaud5191e72010-02-09 20:50:45 +01004710 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004711 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004712 }
4713 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004714 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004715 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004716
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004717 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4718 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004719 err_code |= ERR_ALERT | ERR_FATAL;
4720 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004722 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004723 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004724 /**
4725 * The syntax for hash-type config element is
4726 * hash-type {map-based|consistent} [[<algo>] avalanche]
4727 *
4728 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4729 */
4730 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004731
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004732 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4733 err_code |= ERR_WARN;
4734
4735 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004736 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4737 }
4738 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004739 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4740 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004741 else if (strcmp(args[1], "avalanche") == 0) {
4742 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]);
4743 err_code |= ERR_ALERT | ERR_FATAL;
4744 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004745 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004746 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004747 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004748 err_code |= ERR_ALERT | ERR_FATAL;
4749 goto out;
4750 }
Bhaskar98634f02013-10-29 23:30:51 -04004751
4752 /* set the hash function to use */
4753 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004754 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004755 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004756
4757 /* if consistent with no argument, then avalanche modifier is also applied */
4758 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4759 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004760 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004761 /* set the hash function */
4762 if (!strcmp(args[2], "sdbm")) {
4763 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4764 }
4765 else if (!strcmp(args[2], "djb2")) {
4766 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004767 } else if (!strcmp(args[2], "wt6")) {
4768 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004769 }
4770 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004771 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 -05004772 err_code |= ERR_ALERT | ERR_FATAL;
4773 goto out;
4774 }
4775
4776 /* set the hash modifier */
4777 if (!strcmp(args[3], "avalanche")) {
4778 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4779 }
4780 else if (*args[3]) {
4781 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4782 err_code |= ERR_ALERT | ERR_FATAL;
4783 goto out;
4784 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004785 }
William Lallemanda73203e2012-03-12 12:48:57 +01004786 }
William Lallemanda73203e2012-03-12 12:48:57 +01004787 else if (strcmp(args[0], "unique-id-format") == 0) {
4788 if (!*(args[1])) {
4789 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4790 err_code |= ERR_ALERT | ERR_FATAL;
4791 goto out;
4792 }
William Lallemand3203ff42012-11-11 17:30:56 +01004793 if (*(args[2])) {
4794 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4795 err_code |= ERR_ALERT | ERR_FATAL;
4796 goto out;
4797 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004798 free(curproxy->conf.uniqueid_format_string);
4799 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004800
Willy Tarreau62a61232013-04-12 18:13:46 +02004801 free(curproxy->conf.uif_file);
4802 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4803 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004804 }
William Lallemanda73203e2012-03-12 12:48:57 +01004805
4806 else if (strcmp(args[0], "unique-id-header") == 0) {
4807 if (!*(args[1])) {
4808 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4809 err_code |= ERR_ALERT | ERR_FATAL;
4810 goto out;
4811 }
4812 free(curproxy->header_unique_id);
4813 curproxy->header_unique_id = strdup(args[1]);
4814 }
4815
William Lallemand723b73a2012-02-08 16:37:49 +01004816 else if (strcmp(args[0], "log-format") == 0) {
4817 if (!*(args[1])) {
4818 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4819 err_code |= ERR_ALERT | ERR_FATAL;
4820 goto out;
4821 }
William Lallemand3203ff42012-11-11 17:30:56 +01004822 if (*(args[2])) {
4823 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4824 err_code |= ERR_ALERT | ERR_FATAL;
4825 goto out;
4826 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004827
Willy Tarreau62a61232013-04-12 18:13:46 +02004828 if (curproxy->conf.logformat_string != default_http_log_format &&
4829 curproxy->conf.logformat_string != default_tcp_log_format &&
4830 curproxy->conf.logformat_string != clf_http_log_format)
4831 free(curproxy->conf.logformat_string);
4832 curproxy->conf.logformat_string = strdup(args[1]);
4833
4834 free(curproxy->conf.lfs_file);
4835 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4836 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004837
4838 /* get a chance to improve log-format error reporting by
4839 * reporting the correct line-number when possible.
4840 */
4841 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4842 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4843 file, linenum, curproxy->id);
4844 err_code |= ERR_WARN;
4845 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004846 }
William Lallemand723b73a2012-02-08 16:37:49 +01004847
William Lallemand0f99e342011-10-12 17:50:54 +02004848 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4849 /* delete previous herited or defined syslog servers */
4850 struct logsrv *back;
4851
4852 if (*(args[1]) != 0) {
4853 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4854 err_code |= ERR_ALERT | ERR_FATAL;
4855 goto out;
4856 }
4857
William Lallemand723b73a2012-02-08 16:37:49 +01004858 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4859 LIST_DEL(&tmplogsrv->list);
4860 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004861 }
4862 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004863 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004864 struct logsrv *logsrv;
4865
Willy Tarreaubaaee002006-06-26 02:48:02 +02004866 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004867 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004868 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004869 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004870 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004871 LIST_INIT(&node->list);
4872 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4873 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004874 }
4875 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004876 struct sockaddr_storage *sk;
4877 int port1, port2;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004878 int arg = 0;
4879 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004880
4881 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004882
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004883 /* just after the address, a length may be specified */
4884 if (strcmp(args[arg+2], "len") == 0) {
4885 len = atoi(args[arg+3]);
4886 if (len < 80 || len > 65535) {
4887 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4888 file, linenum, args[arg+3]);
4889 err_code |= ERR_ALERT | ERR_FATAL;
4890 goto out;
4891 }
4892 logsrv->maxlen = len;
4893
4894 /* skip these two args */
4895 arg += 2;
4896 }
4897 else
4898 logsrv->maxlen = MAX_SYSLOG_LEN;
4899
4900 if (logsrv->maxlen > global.max_syslog_len) {
4901 global.max_syslog_len = logsrv->maxlen;
4902 logline = realloc(logline, global.max_syslog_len + 1);
4903 }
4904
4905 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004906 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004907 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004908 err_code |= ERR_ALERT | ERR_FATAL;
4909 goto out;
4910
Willy Tarreaubaaee002006-06-26 02:48:02 +02004911 }
4912
William Lallemand0f99e342011-10-12 17:50:54 +02004913 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004914 if (*(args[arg+3])) {
4915 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004916 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004917 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004918 err_code |= ERR_ALERT | ERR_FATAL;
4919 goto out;
4920
Willy Tarreaubaaee002006-06-26 02:48:02 +02004921 }
4922 }
4923
William Lallemand0f99e342011-10-12 17:50:54 +02004924 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004925 if (*(args[arg+4])) {
4926 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004927 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004928 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004929 err_code |= ERR_ALERT | ERR_FATAL;
4930 goto out;
4931
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004932 }
4933 }
4934
Willy Tarreau902636f2013-03-10 19:44:48 +01004935 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004936 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004937 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004938 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004939 goto out;
4940 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004941
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004942 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004943
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004944 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004945 if (port1 != port2) {
4946 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4947 file, linenum, args[0], args[1]);
4948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
4950 }
4951
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004952 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004953 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004954 }
William Lallemand0f99e342011-10-12 17:50:54 +02004955
4956 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004957 }
4958 else {
4959 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4960 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004961 err_code |= ERR_ALERT | ERR_FATAL;
4962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004963 }
4964 }
4965 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004966 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004967 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004968 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004969 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004970
Willy Tarreau977b8e42006-12-29 14:19:17 +01004971 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004972 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004973
Willy Tarreaubaaee002006-06-26 02:48:02 +02004974 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004975 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4976 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004977 err_code |= ERR_ALERT | ERR_FATAL;
4978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004979 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004980
4981 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004982 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4983 free(curproxy->conn_src.iface_name);
4984 curproxy->conn_src.iface_name = NULL;
4985 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004986
Willy Tarreau902636f2013-03-10 19:44:48 +01004987 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004988 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004989 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004990 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004991 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004992 goto out;
4993 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004994
4995 proto = protocol_by_family(sk->ss_family);
4996 if (!proto || !proto->connect) {
4997 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004998 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004999 err_code |= ERR_ALERT | ERR_FATAL;
5000 goto out;
5001 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005002
5003 if (port1 != port2) {
5004 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5005 file, linenum, args[0], args[1]);
5006 err_code |= ERR_ALERT | ERR_FATAL;
5007 goto out;
5008 }
5009
Willy Tarreauef9a3602012-12-08 22:29:20 +01005010 curproxy->conn_src.source_addr = *sk;
5011 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005012
5013 cur_arg = 2;
5014 while (*(args[cur_arg])) {
5015 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005016#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5017#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005018 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005019 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5020 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005023 }
5024#endif
5025 if (!*args[cur_arg + 1]) {
5026 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5027 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005028 err_code |= ERR_ALERT | ERR_FATAL;
5029 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005030 }
5031
5032 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005033 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5034 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005035 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005036 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5037 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005038 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5039 char *name, *end;
5040
5041 name = args[cur_arg+1] + 7;
5042 while (isspace(*name))
5043 name++;
5044
5045 end = name;
5046 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5047 end++;
5048
Willy Tarreauef9a3602012-12-08 22:29:20 +01005049 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5050 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5051 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5052 curproxy->conn_src.bind_hdr_len = end - name;
5053 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5054 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5055 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005056
5057 /* now look for an occurrence number */
5058 while (isspace(*end))
5059 end++;
5060 if (*end == ',') {
5061 end++;
5062 name = end;
5063 if (*end == '-')
5064 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005065 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005066 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005067 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005068 }
5069
Willy Tarreauef9a3602012-12-08 22:29:20 +01005070 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005071 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5072 " occurrences values smaller than %d.\n",
5073 file, linenum, MAX_HDR_HISTORY);
5074 err_code |= ERR_ALERT | ERR_FATAL;
5075 goto out;
5076 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005077 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005078 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005079
Willy Tarreau902636f2013-03-10 19:44:48 +01005080 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005081 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005082 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005083 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005084 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005085 goto out;
5086 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005087
5088 proto = protocol_by_family(sk->ss_family);
5089 if (!proto || !proto->connect) {
5090 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5091 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005092 err_code |= ERR_ALERT | ERR_FATAL;
5093 goto out;
5094 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005095
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005096 if (port1 != port2) {
5097 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5098 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
5101 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005102 curproxy->conn_src.tproxy_addr = *sk;
5103 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005104 }
5105 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005106#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005107 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005108#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005109#else /* no TPROXY support */
5110 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005111 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005112 err_code |= ERR_ALERT | ERR_FATAL;
5113 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005114#endif
5115 cur_arg += 2;
5116 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005117 }
5118
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005119 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5120#ifdef SO_BINDTODEVICE
5121 if (!*args[cur_arg + 1]) {
5122 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5123 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005124 err_code |= ERR_ALERT | ERR_FATAL;
5125 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005126 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005127 free(curproxy->conn_src.iface_name);
5128 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5129 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005130 global.last_checks |= LSTCHK_NETADM;
5131#else
5132 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5133 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005134 err_code |= ERR_ALERT | ERR_FATAL;
5135 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005136#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005137 cur_arg += 2;
5138 continue;
5139 }
5140 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005141 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005142 err_code |= ERR_ALERT | ERR_FATAL;
5143 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005144 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005145 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005146 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5147 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5148 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005149 err_code |= ERR_ALERT | ERR_FATAL;
5150 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005151 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005152 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005153 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005154 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5155 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005156 err_code |= ERR_ALERT | ERR_FATAL;
5157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005158 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005159
5160 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005161 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005162 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005163 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005165 }
5166 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005167 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005168 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005169 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005170 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005172 }
5173 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005174 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005175 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005176 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005177 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005179 }
5180 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005181 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005182 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005183 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005184 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005186 }
5187 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005188 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005189 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005190 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005191 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005193 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005194 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005195 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005196 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005197 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005198 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005199 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005200 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005201 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005202 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005203 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005204 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005205 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005206 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005207
5208 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5209 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 +01005210 }
5211 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005212 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005213 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005214 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005215 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005216 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005217
5218 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5219 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 +01005220 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005222 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005223 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5224 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005225 err_code |= ERR_ALERT | ERR_FATAL;
5226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005227 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005228
5229 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005230 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005231 args[0], args[1], args[2], (const char **)args+3);
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 }
5235 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
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_REMOVE, REG_ICASE,
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 Tarreaubaaee002006-06-26 02:48:02 +02005241 }
5242 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring 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_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005245 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005246 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005247 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005248 }
5249 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005250 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005251 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005252 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005253 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005255 }
5256 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005257 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005258 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005259 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005260 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005262 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005263 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005264 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005265 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005266 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005267 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005268 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005270 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005271 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005272
Willy Tarreaubaaee002006-06-26 02:48:02 +02005273 if (curproxy == &defproxy) {
5274 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005275 err_code |= ERR_ALERT | ERR_FATAL;
5276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005277 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005278 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005279 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005280
Willy Tarreaubaaee002006-06-26 02:48:02 +02005281 if (*(args[1]) == 0) {
5282 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005283 err_code |= ERR_ALERT | ERR_FATAL;
5284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005285 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005286
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005287 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005288 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5289 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5290 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005291 err_code |= ERR_ALERT | ERR_FATAL;
5292 goto out;
5293 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005294 err_code |= warnif_cond_conflicts(cond,
5295 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5296 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005297 }
5298 else if (*args[2]) {
5299 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5300 file, linenum, args[0], args[2]);
5301 err_code |= ERR_ALERT | ERR_FATAL;
5302 goto out;
5303 }
5304
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005305 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005306 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005307 wl->s = strdup(args[1]);
5308 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005309 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310 }
5311 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005312 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005313 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5314 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005315 err_code |= ERR_ALERT | ERR_FATAL;
5316 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005317 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005318
Willy Tarreauade5ec42010-01-28 19:33:49 +01005319 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005320 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005321 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005322 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005324 }
5325 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005326 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005327 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005328 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005329 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005330 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005331 }
5332 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005333 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005334 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005335 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005336 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005337 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005338 }
5339 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005340 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005341 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5342 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005343 err_code |= ERR_ALERT | ERR_FATAL;
5344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005345 }
5346
Willy Tarreauade5ec42010-01-28 19:33:49 +01005347 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005348 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005349 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005350 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005352 }
5353 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005354 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005355 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005356 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005357 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005358 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005359 }
5360 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005361 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005362 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005363 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005364 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005366 }
5367 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005368 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005369
Willy Tarreaubaaee002006-06-26 02:48:02 +02005370 if (curproxy == &defproxy) {
5371 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005372 err_code |= ERR_ALERT | ERR_FATAL;
5373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005374 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005375 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005376 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005377
Willy Tarreaubaaee002006-06-26 02:48:02 +02005378 if (*(args[1]) == 0) {
5379 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005380 err_code |= ERR_ALERT | ERR_FATAL;
5381 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005382 }
5383
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005384 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005385 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5386 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5387 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005388 err_code |= ERR_ALERT | ERR_FATAL;
5389 goto out;
5390 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005391 err_code |= warnif_cond_conflicts(cond,
5392 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5393 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005394 }
5395 else if (*args[2]) {
5396 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5397 file, linenum, args[0], args[2]);
5398 err_code |= ERR_ALERT | ERR_FATAL;
5399 goto out;
5400 }
5401
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005402 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005403 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005404 wl->s = strdup(args[1]);
5405 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005406 }
5407 else if (!strcmp(args[0], "errorloc") ||
5408 !strcmp(args[0], "errorloc302") ||
5409 !strcmp(args[0], "errorloc303")) { /* error location */
5410 int errnum, errlen;
5411 char *err;
5412
Willy Tarreau977b8e42006-12-29 14:19:17 +01005413 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005414 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005415
Willy Tarreaubaaee002006-06-26 02:48:02 +02005416 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005417 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005418 err_code |= ERR_ALERT | ERR_FATAL;
5419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005420 }
5421
5422 errnum = atol(args[1]);
5423 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005424 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5425 err = malloc(errlen);
5426 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005427 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005428 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5429 err = malloc(errlen);
5430 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005431 }
5432
Willy Tarreau0f772532006-12-23 20:51:41 +01005433 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5434 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005435 chunk_destroy(&curproxy->errmsg[rc]);
5436 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005437 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005438 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005439 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005440
5441 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreau09a4a0a2015-09-27 15:13:30 +02005442 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
5443 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005444 free(err);
5445 }
5446 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005447 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5448 int errnum, errlen, fd;
5449 char *err;
5450 struct stat stat;
5451
5452 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005453 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005454
5455 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005456 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005457 err_code |= ERR_ALERT | ERR_FATAL;
5458 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005459 }
5460
5461 fd = open(args[2], O_RDONLY);
5462 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5463 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5464 file, linenum, args[2], args[1]);
5465 if (fd >= 0)
5466 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005467 err_code |= ERR_ALERT | ERR_FATAL;
5468 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005469 }
5470
Willy Tarreau27a674e2009-08-17 07:23:33 +02005471 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005472 errlen = stat.st_size;
5473 } else {
5474 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005475 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005476 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005477 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005478 }
5479
5480 err = malloc(errlen); /* malloc() must succeed during parsing */
5481 errnum = read(fd, err, errlen);
5482 if (errnum != errlen) {
5483 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5484 file, linenum, args[2], args[1]);
5485 close(fd);
5486 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005487 err_code |= ERR_ALERT | ERR_FATAL;
5488 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005489 }
5490 close(fd);
5491
5492 errnum = atol(args[1]);
5493 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5494 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005495 chunk_destroy(&curproxy->errmsg[rc]);
5496 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005497 break;
5498 }
5499 }
5500
5501 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreau09a4a0a2015-09-27 15:13:30 +02005502 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
5503 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005504 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005505 free(err);
5506 }
5507 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005508 else if (!strcmp(args[0], "compression")) {
5509 struct comp *comp;
5510 if (curproxy->comp == NULL) {
5511 comp = calloc(1, sizeof(struct comp));
5512 curproxy->comp = comp;
5513 } else {
5514 comp = curproxy->comp;
5515 }
5516
5517 if (!strcmp(args[1], "algo")) {
5518 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005519 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005520
William Lallemand82fe75c2012-10-23 10:25:10 +02005521 cur_arg = 2;
5522 if (!*args[cur_arg]) {
5523 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5524 file, linenum, args[0]);
5525 err_code |= ERR_ALERT | ERR_FATAL;
5526 goto out;
5527 }
5528 while (*(args[cur_arg])) {
5529 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5530 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5531 file, linenum, args[0], args[cur_arg]);
5532 err_code |= ERR_ALERT | ERR_FATAL;
5533 goto out;
5534 }
William Lallemand552df672012-11-07 13:21:47 +01005535 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5536 curproxy->comp->algos->end(&ctx);
5537 } else {
5538 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5539 file, linenum, args[0], args[cur_arg]);
5540 err_code |= ERR_ALERT | ERR_FATAL;
5541 goto out;
5542 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005543 cur_arg ++;
5544 continue;
5545 }
5546 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005547 else if (!strcmp(args[1], "offload")) {
5548 comp->offload = 1;
5549 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005550 else if (!strcmp(args[1], "type")) {
5551 int cur_arg;
5552 cur_arg = 2;
5553 if (!*args[cur_arg]) {
5554 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5555 file, linenum, args[0]);
5556 err_code |= ERR_ALERT | ERR_FATAL;
5557 goto out;
5558 }
5559 while (*(args[cur_arg])) {
5560 comp_append_type(comp, args[cur_arg]);
5561 cur_arg ++;
5562 continue;
5563 }
5564 }
5565 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005566 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005567 file, linenum, args[0]);
5568 err_code |= ERR_ALERT | ERR_FATAL;
5569 goto out;
5570 }
5571 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005572 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005573 struct cfg_kw_list *kwl;
5574 int index;
5575
5576 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5577 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5578 if (kwl->kw[index].section != CFG_LISTEN)
5579 continue;
5580 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5581 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005582 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005583 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005584 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005585 err_code |= ERR_ALERT | ERR_FATAL;
5586 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005587 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005588 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005589 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005590 err_code |= ERR_WARN;
5591 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005592 }
Willy Tarreau93893792009-07-23 13:19:11 +02005593 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005594 }
5595 }
5596 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005597
Willy Tarreau6daf3432008-01-22 16:44:08 +01005598 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005599 err_code |= ERR_ALERT | ERR_FATAL;
5600 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005601 }
Willy Tarreau93893792009-07-23 13:19:11 +02005602 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005603 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005604 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605}
5606
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005607int
5608cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5609{
5610
5611 int err_code = 0;
5612 const char *err;
5613
5614 if (!strcmp(args[0], "userlist")) { /* new userlist */
5615 struct userlist *newul;
5616
5617 if (!*args[1]) {
5618 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5619 file, linenum, args[0]);
5620 err_code |= ERR_ALERT | ERR_FATAL;
5621 goto out;
5622 }
5623
5624 err = invalid_char(args[1]);
5625 if (err) {
5626 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5627 file, linenum, *err, args[0], args[1]);
5628 err_code |= ERR_ALERT | ERR_FATAL;
5629 goto out;
5630 }
5631
5632 for (newul = userlist; newul; newul = newul->next)
5633 if (!strcmp(newul->name, args[1])) {
5634 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5635 file, linenum, args[1]);
5636 err_code |= ERR_WARN;
5637 goto out;
5638 }
5639
5640 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5641 if (!newul) {
5642 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5643 err_code |= ERR_ALERT | ERR_ABORT;
5644 goto out;
5645 }
5646
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005647 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005648 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005649 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5650 err_code |= ERR_ALERT | ERR_ABORT;
5651 goto out;
5652 }
5653
5654 newul->next = userlist;
5655 userlist = newul;
5656
5657 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005658 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005659 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005660 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005661
5662 if (!*args[1]) {
5663 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5664 file, linenum, args[0]);
5665 err_code |= ERR_ALERT | ERR_FATAL;
5666 goto out;
5667 }
5668
5669 err = invalid_char(args[1]);
5670 if (err) {
5671 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5672 file, linenum, *err, args[0], args[1]);
5673 err_code |= ERR_ALERT | ERR_FATAL;
5674 goto out;
5675 }
5676
William Lallemandfaf33152015-05-28 18:03:51 +02005677 if (!userlist)
5678 goto out;
5679
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005680 for (ag = userlist->groups; ag; ag = ag->next)
5681 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005682 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5683 file, linenum, args[1], userlist->name);
5684 err_code |= ERR_ALERT;
5685 goto out;
5686 }
5687
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005688 ag = calloc(1, sizeof(*ag));
5689 if (!ag) {
5690 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5691 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005692 goto out;
5693 }
5694
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005695 ag->name = strdup(args[1]);
5696 if (!ag) {
5697 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5698 err_code |= ERR_ALERT | ERR_ABORT;
5699 goto out;
5700 }
5701
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005702 cur_arg = 2;
5703
5704 while (*args[cur_arg]) {
5705 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005706 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005707 cur_arg += 2;
5708 continue;
5709 } else {
5710 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5711 file, linenum, args[0]);
5712 err_code |= ERR_ALERT | ERR_FATAL;
5713 goto out;
5714 }
5715 }
5716
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005717 ag->next = userlist->groups;
5718 userlist->groups = ag;
5719
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005720 } else if (!strcmp(args[0], "user")) { /* new user */
5721 struct auth_users *newuser;
5722 int cur_arg;
5723
5724 if (!*args[1]) {
5725 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5726 file, linenum, args[0]);
5727 err_code |= ERR_ALERT | ERR_FATAL;
5728 goto out;
5729 }
William Lallemandfaf33152015-05-28 18:03:51 +02005730 if (!userlist)
5731 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005732
5733 for (newuser = userlist->users; newuser; newuser = newuser->next)
5734 if (!strcmp(newuser->user, args[1])) {
5735 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5736 file, linenum, args[1], userlist->name);
5737 err_code |= ERR_ALERT;
5738 goto out;
5739 }
5740
5741 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5742 if (!newuser) {
5743 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5744 err_code |= ERR_ALERT | ERR_ABORT;
5745 goto out;
5746 }
5747
5748 newuser->user = strdup(args[1]);
5749
5750 newuser->next = userlist->users;
5751 userlist->users = newuser;
5752
5753 cur_arg = 2;
5754
5755 while (*args[cur_arg]) {
5756 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté2c8d7002014-08-29 20:20:02 +02005757#ifdef CONFIG_HAP_CRYPT
5758 if (!crypt("", args[cur_arg + 1])) {
5759 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
5760 file, linenum, newuser->user);
5761 err_code |= ERR_ALERT | ERR_FATAL;
5762 goto out;
5763 }
5764#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005765 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5766 file, linenum);
5767 err_code |= ERR_ALERT;
5768#endif
5769 newuser->pass = strdup(args[cur_arg + 1]);
5770 cur_arg += 2;
5771 continue;
5772 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5773 newuser->pass = strdup(args[cur_arg + 1]);
5774 newuser->flags |= AU_O_INSECURE;
5775 cur_arg += 2;
5776 continue;
5777 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005778 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005779 cur_arg += 2;
5780 continue;
5781 } else {
5782 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5783 file, linenum, args[0]);
5784 err_code |= ERR_ALERT | ERR_FATAL;
5785 goto out;
5786 }
5787 }
5788 } else {
5789 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5790 err_code |= ERR_ALERT | ERR_FATAL;
5791 }
5792
5793out:
5794 return err_code;
5795}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005796
5797/*
5798 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005799 * Returns the error code, 0 if OK, or any combination of :
5800 * - ERR_ABORT: must abort ASAP
5801 * - ERR_FATAL: we can continue parsing but not start the service
5802 * - ERR_WARN: a warning has been emitted
5803 * - ERR_ALERT: an alert has been emitted
5804 * Only the two first ones can stop processing, the two others are just
5805 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005806 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005807int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005808{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005809 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005810 FILE *f;
5811 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005812 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005813 struct cfg_section *cs = NULL;
5814 struct cfg_section *ics;
5815
5816 /* Register internal sections */
5817 if (!cfg_register_section("listen", cfg_parse_listen) ||
5818 !cfg_register_section("frontend", cfg_parse_listen) ||
5819 !cfg_register_section("backend", cfg_parse_listen) ||
5820 !cfg_register_section("ruleset", cfg_parse_listen) ||
5821 !cfg_register_section("defaults", cfg_parse_listen) ||
5822 !cfg_register_section("global", cfg_parse_global) ||
5823 !cfg_register_section("userlist", cfg_parse_users) ||
5824 !cfg_register_section("peers", cfg_parse_peers))
5825 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005826
Willy Tarreaubaaee002006-06-26 02:48:02 +02005827 if ((f=fopen(file,"r")) == NULL)
5828 return -1;
5829
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005830 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005831 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005832 char *end;
5833 char *args[MAX_LINE_ARGS + 1];
5834 char *line = thisline;
5835
Willy Tarreaubaaee002006-06-26 02:48:02 +02005836 linenum++;
5837
5838 end = line + strlen(line);
5839
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005840 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5841 /* Check if we reached the limit and the last char is not \n.
5842 * Watch out for the last line without the terminating '\n'!
5843 */
5844 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005845 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005846 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005847 }
5848
Willy Tarreaubaaee002006-06-26 02:48:02 +02005849 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005850 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005851 line++;
5852
5853 arg = 0;
5854 args[arg] = line;
5855
5856 while (*line && arg < MAX_LINE_ARGS) {
5857 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5858 * C equivalent value. Other combinations left unchanged (eg: \1).
5859 */
5860 if (*line == '\\') {
5861 int skip = 0;
5862 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5863 *line = line[1];
5864 skip = 1;
5865 }
5866 else if (line[1] == 'r') {
5867 *line = '\r';
5868 skip = 1;
5869 }
5870 else if (line[1] == 'n') {
5871 *line = '\n';
5872 skip = 1;
5873 }
5874 else if (line[1] == 't') {
5875 *line = '\t';
5876 skip = 1;
5877 }
5878 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005879 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005880 unsigned char hex1, hex2;
5881 hex1 = toupper(line[2]) - '0';
5882 hex2 = toupper(line[3]) - '0';
5883 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5884 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5885 *line = (hex1<<4) + hex2;
5886 skip = 3;
5887 }
5888 else {
5889 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005890 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 }
5892 }
5893 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005894 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005895 end -= skip;
5896 }
5897 line++;
5898 }
5899 else if (*line == '#' || *line == '\n' || *line == '\r') {
5900 /* end of string, end of loop */
5901 *line = 0;
5902 break;
5903 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005904 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005905 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005906 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005907 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005908 line++;
5909 args[++arg] = line;
5910 }
5911 else {
5912 line++;
5913 }
5914 }
5915
5916 /* empty line */
5917 if (!**args)
5918 continue;
5919
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005920 if (*line) {
5921 /* we had to stop due to too many args.
5922 * Let's terminate the string, print the offending part then cut the
5923 * last arg.
5924 */
5925 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5926 line++;
5927 *line = '\0';
5928
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005929 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005930 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005931 err_code |= ERR_ALERT | ERR_FATAL;
5932 args[arg] = line;
5933 }
5934
Willy Tarreau540abe42007-05-02 20:50:16 +02005935 /* zero out remaining args and ensure that at least one entry
5936 * is zeroed out.
5937 */
5938 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005939 args[arg] = line;
5940 }
5941
Willy Tarreau3842f002009-06-14 11:39:52 +02005942 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005943 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005944 char *tmp;
5945
Willy Tarreau3842f002009-06-14 11:39:52 +02005946 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005947 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005948 for (arg=0; *args[arg+1]; arg++)
5949 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005950 *tmp = '\0'; // fix the next arg to \0
5951 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005952 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005953 else if (!strcmp(args[0], "default")) {
5954 kwm = KWM_DEF;
5955 for (arg=0; *args[arg+1]; arg++)
5956 args[arg] = args[arg+1]; // shift args after inversion
5957 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005958
William Lallemand0f99e342011-10-12 17:50:54 +02005959 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5960 strcmp(args[0], "log") != 0) {
5961 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005962 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005963 }
5964
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005965 /* detect section start */
5966 list_for_each_entry(ics, &sections, list) {
5967 if (strcmp(args[0], ics->section_name) == 0) {
5968 cursection = ics->section_name;
5969 cs = ics;
5970 break;
5971 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005972 }
5973
Willy Tarreaubaaee002006-06-26 02:48:02 +02005974 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005975 if (cs)
5976 err_code |= cs->section_parser(file, linenum, args, kwm);
5977 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005978 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005979 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005980 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005981
5982 if (err_code & ERR_ABORT)
5983 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005984 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005985 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005986 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005987 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005988}
5989
Willy Tarreau5436afc2014-09-16 12:17:36 +02005990/* This function propagates processes from frontend <from> to backend <to> so
5991 * that it is always guaranteed that a backend pointed to by a frontend is
5992 * bound to all of its processes. After that, if the target is a "listen"
5993 * instance, the function recursively descends the target's own targets along
5994 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
5995 * checked first to ensure that <to> is already bound to all processes of
5996 * <from>, there is no risk of looping and we ensure to follow the shortest
5997 * path to the destination.
5998 *
5999 * It is possible to set <to> to NULL for the first call so that the function
6000 * takes care of visiting the initial frontend in <from>.
6001 *
6002 * It is important to note that the function relies on the fact that all names
6003 * have already been resolved.
6004 */
6005void propagate_processes(struct proxy *from, struct proxy *to)
6006{
6007 struct switching_rule *rule;
6008 struct hdr_exp *exp;
6009
6010 if (to) {
6011 /* check whether we need to go down */
6012 if (from->bind_proc &&
6013 (from->bind_proc & to->bind_proc) == from->bind_proc)
6014 return;
6015
6016 if (!from->bind_proc && !to->bind_proc)
6017 return;
6018
6019 to->bind_proc = from->bind_proc ?
6020 (to->bind_proc | from->bind_proc) : 0;
6021
6022 /* now propagate down */
6023 from = to;
6024 }
6025
Willy Tarreau7110f382014-12-18 13:56:26 +01006026 if (!(from->cap & PR_CAP_FE))
Willy Tarreau5436afc2014-09-16 12:17:36 +02006027 return;
6028
Willy Tarreaued061c02014-12-18 14:00:43 +01006029 if (from->state == PR_STSTOPPED)
6030 return;
6031
Willy Tarreau5436afc2014-09-16 12:17:36 +02006032 /* default_backend */
6033 if (from->defbe.be)
6034 propagate_processes(from, from->defbe.be);
6035
6036 /* use_backend */
6037 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bontéc8d57de2014-10-02 19:56:25 +02006038 if (rule->dynamic)
6039 continue;
Willy Tarreau5436afc2014-09-16 12:17:36 +02006040 to = rule->be.backend;
6041 propagate_processes(from, to);
6042 }
6043
6044 /* reqsetbe */
6045 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6046 if (exp->action != ACT_SETBE)
6047 continue;
6048 to = (struct proxy *)exp->replace;
6049 propagate_processes(from, to);
6050 }
6051}
6052
Willy Tarreaubb925012009-07-23 13:36:36 +02006053/*
6054 * Returns the error code, 0 if OK, or any combination of :
6055 * - ERR_ABORT: must abort ASAP
6056 * - ERR_FATAL: we can continue parsing but not start the service
6057 * - ERR_WARN: a warning has been emitted
6058 * - ERR_ALERT: an alert has been emitted
6059 * Only the two first ones can stop processing, the two others are just
6060 * indicators.
6061 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006062int check_config_validity()
6063{
6064 int cfgerr = 0;
6065 struct proxy *curproxy = NULL;
6066 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006067 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006068 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006069 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006070
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006071 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006072 /*
6073 * Now, check for the integrity of all that we have collected.
6074 */
6075
6076 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006077 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006078
Willy Tarreau193b8c62012-11-22 00:17:38 +01006079 if (!global.tune.max_http_hdr)
6080 global.tune.max_http_hdr = MAX_HTTP_HDR;
6081
6082 if (!global.tune.cookie_len)
6083 global.tune.cookie_len = CAPTURE_LEN;
6084
6085 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6086
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006087 /* Post initialisation of the users and groups lists. */
6088 err_code = userlist_postinit();
6089 if (err_code != ERR_NONE)
6090 goto out;
6091
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006092 /* first, we will invert the proxy list order */
6093 curproxy = NULL;
6094 while (proxy) {
6095 struct proxy *next;
6096
6097 next = proxy->next;
6098 proxy->next = curproxy;
6099 curproxy = proxy;
6100 if (!next)
6101 break;
6102 proxy = next;
6103 }
6104
Willy Tarreau91b00c22014-09-16 13:41:21 +02006105 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006106 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006107 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006108 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006109 struct tcp_rule *trule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006110 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006111 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006112
Willy Tarreau050536d2012-10-04 08:47:34 +02006113 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006114 /* proxy ID not set, use automatic numbering with first
6115 * spare entry starting with next_pxid.
6116 */
6117 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6118 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6119 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006120 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006121 next_pxid++;
6122
Willy Tarreau55ea7572007-06-17 19:56:27 +02006123
Willy Tarreaubaaee002006-06-26 02:48:02 +02006124 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006125 /* ensure we don't keep listeners uselessly bound */
6126 stop_proxy(curproxy);
Willy Tarreaud72af0a2015-05-01 19:59:56 +02006127 free((void *)curproxy->table.peers.name);
6128 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006129 continue;
6130 }
6131
Willy Tarreau102df612014-05-07 23:56:38 +02006132 /* Check multi-process mode compatibility for the current proxy */
6133
6134 if (curproxy->bind_proc) {
6135 /* an explicit bind-process was specified, let's check how many
6136 * processes remain.
6137 */
David Carlier6de4c2f2015-07-02 07:00:17 +00006138 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02006139
6140 curproxy->bind_proc &= nbits(global.nbproc);
6141 if (!curproxy->bind_proc && nbproc == 1) {
6142 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);
6143 curproxy->bind_proc = 1;
6144 }
6145 else if (!curproxy->bind_proc && nbproc > 1) {
6146 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);
6147 curproxy->bind_proc = 0;
6148 }
6149 }
6150
Willy Tarreau3d209582014-05-09 17:06:11 +02006151 /* check and reduce the bind-proc of each listener */
6152 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6153 unsigned long mask;
6154
6155 if (!bind_conf->bind_proc)
6156 continue;
6157
6158 mask = nbits(global.nbproc);
6159 if (curproxy->bind_proc)
6160 mask &= curproxy->bind_proc;
6161 /* mask cannot be null here thanks to the previous checks */
6162
David Carlier6de4c2f2015-07-02 07:00:17 +00006163 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02006164 bind_conf->bind_proc &= mask;
6165
6166 if (!bind_conf->bind_proc && nbproc == 1) {
6167 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",
6168 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6169 bind_conf->bind_proc = mask & ~(mask - 1);
6170 }
6171 else if (!bind_conf->bind_proc && nbproc > 1) {
6172 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",
6173 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6174 bind_conf->bind_proc = 0;
6175 }
6176 }
6177
Willy Tarreauff01a212009-03-15 13:46:16 +01006178 switch (curproxy->mode) {
6179 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006180 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006181 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006182 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6183 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006184 cfgerr++;
6185 }
6186
6187 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006188 Warning("config : servers will be ignored for %s '%s'.\n",
6189 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006190 break;
6191
6192 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006193 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006194 break;
6195
6196 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006197 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006198 break;
6199 }
6200
Willy Tarreauc7c1e552015-08-11 11:36:45 +02006201 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
6202 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
6203 proxy_type_str(curproxy), curproxy->id);
6204 err_code |= ERR_WARN;
6205 }
6206
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006207 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006208 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006209 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006210 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6211 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006212 cfgerr++;
6213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006214#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006215 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006216 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6217 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006218 cfgerr++;
6219 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006220#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006221 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006222 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6223 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006224 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006225 }
6226 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006227 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006228 /* If no LB algo is set in a backend, and we're not in
6229 * transparent mode, dispatch mode nor proxy mode, we
6230 * want to use balance roundrobin by default.
6231 */
6232 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6233 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006234 }
6235 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006236
Willy Tarreau1620ec32011-08-06 17:05:02 +02006237 if (curproxy->options & PR_O_DISPATCH)
6238 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6239 else if (curproxy->options & PR_O_HTTP_PROXY)
6240 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6241 else if (curproxy->options & PR_O_TRANSP)
6242 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006243
Willy Tarreau1620ec32011-08-06 17:05:02 +02006244 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6245 if (curproxy->options & PR_O_DISABLE404) {
6246 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6247 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6248 err_code |= ERR_WARN;
6249 curproxy->options &= ~PR_O_DISABLE404;
6250 }
6251 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6252 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6253 "send-state", proxy_type_str(curproxy), curproxy->id);
6254 err_code |= ERR_WARN;
6255 curproxy->options &= ~PR_O2_CHK_SNDST;
6256 }
Willy Tarreauef781042010-01-27 11:53:01 +01006257 }
6258
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006259 /* if a default backend was specified, let's find it */
6260 if (curproxy->defbe.name) {
6261 struct proxy *target;
6262
Alex Williams96532db2009-11-01 21:27:13 -05006263 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006264 if (!target) {
6265 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6266 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006267 cfgerr++;
6268 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006269 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6270 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006271 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006272 } else {
6273 free(curproxy->defbe.name);
6274 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006275
6276 /* Emit a warning if this proxy also has some servers */
6277 if (curproxy->srv) {
6278 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6279 curproxy->id);
6280 err_code |= ERR_WARN;
6281 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006282 }
6283 }
6284
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006285 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006286 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6287 /* map jump target for ACT_SETBE in req_rep chain */
6288 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006289 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006290 struct proxy *target;
6291
Willy Tarreaua496b602006-12-17 23:15:24 +01006292 if (exp->action != ACT_SETBE)
6293 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006294
Alex Williams96532db2009-11-01 21:27:13 -05006295 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006296 if (!target) {
6297 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6298 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006299 cfgerr++;
6300 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006301 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6302 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006303 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006304 } else {
6305 free((void *)exp->replace);
6306 exp->replace = (const char *)target;
6307 }
6308 }
6309 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006310
6311 /* find the target proxy for 'use_backend' rules */
6312 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006313 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006314 struct logformat_node *node;
6315 char *pxname;
6316
6317 /* Try to parse the string as a log format expression. If the result
6318 * of the parsing is only one entry containing a simple string, then
6319 * it's a standard string corresponding to a static rule, thus the
6320 * parsing is cancelled and be.name is restored to be resolved.
6321 */
6322 pxname = rule->be.name;
6323 LIST_INIT(&rule->be.expr);
6324 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6325 curproxy->conf.args.file, curproxy->conf.args.line);
6326 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6327
6328 if (!LIST_ISEMPTY(&rule->be.expr)) {
6329 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6330 rule->dynamic = 1;
6331 free(pxname);
6332 continue;
6333 }
6334 /* simple string: free the expression and fall back to static rule */
6335 free(node->arg);
6336 free(node);
6337 }
6338
6339 rule->dynamic = 0;
6340 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006341
Alex Williams96532db2009-11-01 21:27:13 -05006342 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006343
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006344 if (!target) {
6345 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6346 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006347 cfgerr++;
6348 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006349 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6350 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006351 cfgerr++;
6352 } else {
6353 free((void *)rule->be.name);
6354 rule->be.backend = target;
6355 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006356 }
6357
Willy Tarreau5436afc2014-09-16 12:17:36 +02006358 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006359 list_for_each_entry(srule, &curproxy->server_rules, list) {
6360 struct server *target = findserver(curproxy, srule->srv.name);
6361
6362 if (!target) {
6363 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6364 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6365 cfgerr++;
6366 continue;
6367 }
6368 free((void *)srule->srv.name);
6369 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006370 }
6371
Emeric Brunb982a3d2010-01-04 15:45:53 +01006372 /* find the target table for 'stick' rules */
6373 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6374 struct proxy *target;
6375
Emeric Brun1d33b292010-01-04 15:47:17 +01006376 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6377 if (mrule->flags & STK_IS_STORE)
6378 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6379
Emeric Brunb982a3d2010-01-04 15:45:53 +01006380 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006381 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006382 else
6383 target = curproxy;
6384
6385 if (!target) {
6386 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6387 curproxy->id, mrule->table.name);
6388 cfgerr++;
6389 }
6390 else if (target->table.size == 0) {
6391 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6392 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6393 cfgerr++;
6394 }
Willy Tarreau12785782012-04-27 21:37:17 +02006395 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6396 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006397 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6398 cfgerr++;
6399 }
6400 else {
6401 free((void *)mrule->table.name);
6402 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006403 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006404 }
6405 }
6406
6407 /* find the target table for 'store response' rules */
6408 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6409 struct proxy *target;
6410
Emeric Brun1d33b292010-01-04 15:47:17 +01006411 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6412
Emeric Brunb982a3d2010-01-04 15:45:53 +01006413 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006414 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006415 else
6416 target = curproxy;
6417
6418 if (!target) {
6419 Alert("Proxy '%s': unable to find store table '%s'.\n",
6420 curproxy->id, mrule->table.name);
6421 cfgerr++;
6422 }
6423 else if (target->table.size == 0) {
6424 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6425 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6426 cfgerr++;
6427 }
Willy Tarreau12785782012-04-27 21:37:17 +02006428 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6429 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006430 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6431 cfgerr++;
6432 }
6433 else {
6434 free((void *)mrule->table.name);
6435 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006436 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006437 }
6438 }
6439
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006440 /* find the target table for 'tcp-request' layer 4 rules */
6441 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6442 struct proxy *target;
6443
Willy Tarreaub4c84932013-07-23 19:15:30 +02006444 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006445 continue;
6446
6447 if (trule->act_prm.trk_ctr.table.n)
6448 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6449 else
6450 target = curproxy;
6451
6452 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006453 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6454 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006455 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006456 cfgerr++;
6457 }
6458 else if (target->table.size == 0) {
6459 Alert("Proxy '%s': table '%s' used but not configured.\n",
6460 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6461 cfgerr++;
6462 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006463 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6464 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6465 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 +01006466 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006467 cfgerr++;
6468 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006469 else {
6470 free(trule->act_prm.trk_ctr.table.n);
6471 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006472 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006473 * to pass a list of counters to track and allocate them right here using
6474 * stktable_alloc_data_type().
6475 */
6476 }
6477 }
6478
Willy Tarreaud1f96522010-08-03 19:34:32 +02006479 /* find the target table for 'tcp-request' layer 6 rules */
6480 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6481 struct proxy *target;
6482
Willy Tarreaub4c84932013-07-23 19:15:30 +02006483 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006484 continue;
6485
6486 if (trule->act_prm.trk_ctr.table.n)
6487 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6488 else
6489 target = curproxy;
6490
6491 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006492 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6493 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006494 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006495 cfgerr++;
6496 }
6497 else if (target->table.size == 0) {
6498 Alert("Proxy '%s': table '%s' used but not configured.\n",
6499 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6500 cfgerr++;
6501 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006502 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6503 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6504 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 +01006505 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006506 cfgerr++;
6507 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006508 else {
6509 free(trule->act_prm.trk_ctr.table.n);
6510 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006511 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006512 * to pass a list of counters to track and allocate them right here using
6513 * stktable_alloc_data_type().
6514 */
6515 }
6516 }
6517
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006518 /* move any "block" rules at the beginning of the http-request rules */
6519 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6520 /* insert block_rules into http_req_rules at the beginning */
6521 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6522 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6523 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6524 curproxy->http_req_rules.n = curproxy->block_rules.n;
6525 LIST_INIT(&curproxy->block_rules);
6526 }
6527
Emeric Brun32da3c42010-09-23 18:39:19 +02006528 if (curproxy->table.peers.name) {
6529 struct peers *curpeers = peers;
6530
6531 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6532 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6533 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006534 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006535 break;
6536 }
6537 }
6538
6539 if (!curpeers) {
6540 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6541 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006542 free((void *)curproxy->table.peers.name);
6543 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006544 cfgerr++;
6545 }
Willy Tarreau34d05b02015-05-01 20:02:17 +02006546 else if (curpeers->state == PR_STSTOPPED) {
6547 /* silently disable this peers section */
6548 curproxy->table.peers.p = NULL;
6549 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006550 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006551 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6552 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006553 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006554 cfgerr++;
6555 }
6556 }
6557
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006558 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006559 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006560 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6561 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6562 "proxy", curproxy->id);
6563 cfgerr++;
6564 goto out_uri_auth_compat;
6565 }
6566
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006567 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006568 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006569 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006570 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006571
Willy Tarreau95fa4692010-02-01 13:05:50 +01006572 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6573 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006574
6575 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006576 uri_auth_compat_req[i++] = "realm";
6577 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6578 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006579
Willy Tarreau95fa4692010-02-01 13:05:50 +01006580 uri_auth_compat_req[i++] = "unless";
6581 uri_auth_compat_req[i++] = "{";
6582 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6583 uri_auth_compat_req[i++] = "}";
6584 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006585
Willy Tarreauff011f22011-01-06 17:51:27 +01006586 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6587 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006588 cfgerr++;
6589 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006590 }
6591
Willy Tarreauff011f22011-01-06 17:51:27 +01006592 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006593
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006594 if (curproxy->uri_auth->auth_realm) {
6595 free(curproxy->uri_auth->auth_realm);
6596 curproxy->uri_auth->auth_realm = NULL;
6597 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006598
6599 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006600 }
6601out_uri_auth_compat:
6602
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006603 /* compile the log format */
6604 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006605 if (curproxy->conf.logformat_string != default_http_log_format &&
6606 curproxy->conf.logformat_string != default_tcp_log_format &&
6607 curproxy->conf.logformat_string != clf_http_log_format)
6608 free(curproxy->conf.logformat_string);
6609 curproxy->conf.logformat_string = NULL;
6610 free(curproxy->conf.lfs_file);
6611 curproxy->conf.lfs_file = NULL;
6612 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006613 }
6614
Willy Tarreau62a61232013-04-12 18:13:46 +02006615 if (curproxy->conf.logformat_string) {
6616 curproxy->conf.args.ctx = ARGC_LOG;
6617 curproxy->conf.args.file = curproxy->conf.lfs_file;
6618 curproxy->conf.args.line = curproxy->conf.lfs_line;
6619 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006620 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006621 curproxy->conf.args.file = NULL;
6622 curproxy->conf.args.line = 0;
6623 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006624
Willy Tarreau62a61232013-04-12 18:13:46 +02006625 if (curproxy->conf.uniqueid_format_string) {
6626 curproxy->conf.args.ctx = ARGC_UIF;
6627 curproxy->conf.args.file = curproxy->conf.uif_file;
6628 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006629 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbach543b9782014-12-18 15:44:58 +08006630 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006631 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006632 curproxy->conf.args.file = NULL;
6633 curproxy->conf.args.line = 0;
6634 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006635
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006636 /* only now we can check if some args remain unresolved.
6637 * This must be done after the users and groups resolution.
6638 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006639 cfgerr += smp_resolve_args(curproxy);
6640 if (!cfgerr)
6641 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006642
Willy Tarreau2738a142006-07-08 17:28:09 +02006643 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006644 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006645 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006646 (!curproxy->timeout.connect ||
6647 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006648 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006649 " | While not properly invalid, you will certainly encounter various problems\n"
6650 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006651 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006652 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006653 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006654 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006655
Willy Tarreau1fa31262007-12-03 00:36:16 +01006656 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6657 * We must still support older configurations, so let's find out whether those
6658 * parameters have been set or must be copied from contimeouts.
6659 */
6660 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006661 if (!curproxy->timeout.tarpit ||
6662 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006663 /* tarpit timeout not set. We search in the following order:
6664 * default.tarpit, curr.connect, default.connect.
6665 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006666 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006667 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006668 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006669 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006670 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006671 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006672 }
6673 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006674 (!curproxy->timeout.queue ||
6675 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006676 /* queue timeout not set. We search in the following order:
6677 * default.queue, curr.connect, default.connect.
6678 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006679 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006680 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006681 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006682 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006683 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006684 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006685 }
6686 }
6687
Willy Tarreau1620ec32011-08-06 17:05:02 +02006688 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006689 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6690 curproxy->check_req = (char *)malloc(curproxy->check_len);
6691 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006692 }
6693
Willy Tarreau215663d2014-06-13 18:30:23 +02006694 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6695 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6696 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6697 proxy_type_str(curproxy), curproxy->id);
6698 err_code |= ERR_WARN;
6699 }
6700
Willy Tarreau193b8c62012-11-22 00:17:38 +01006701 /* ensure that cookie capture length is not too large */
6702 if (curproxy->capture_len >= global.tune.cookie_len) {
6703 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6704 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6705 err_code |= ERR_WARN;
6706 curproxy->capture_len = global.tune.cookie_len - 1;
6707 }
6708
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006709 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006710 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006711 curproxy->req_cap_pool = create_pool("ptrcap",
6712 curproxy->nb_req_cap * sizeof(char *),
6713 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006714 }
6715
6716 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006717 curproxy->rsp_cap_pool = create_pool("ptrcap",
6718 curproxy->nb_rsp_cap * sizeof(char *),
6719 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006720 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006721
Willy Tarreaubaaee002006-06-26 02:48:02 +02006722 /* first, we will invert the servers list order */
6723 newsrv = NULL;
6724 while (curproxy->srv) {
6725 struct server *next;
6726
6727 next = curproxy->srv->next;
6728 curproxy->srv->next = newsrv;
6729 newsrv = curproxy->srv;
6730 if (!next)
6731 break;
6732 curproxy->srv = next;
6733 }
6734
Willy Tarreau17edc812014-01-03 12:14:34 +01006735 /* Check that no server name conflicts. This causes trouble in the stats.
6736 * We only emit a warning for the first conflict affecting each server,
6737 * in order to avoid combinatory explosion if all servers have the same
6738 * name. We do that only for servers which do not have an explicit ID,
6739 * because these IDs were made also for distinguishing them and we don't
6740 * want to annoy people who correctly manage them.
6741 */
6742 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6743 struct server *other_srv;
6744
6745 if (newsrv->puid)
6746 continue;
6747
6748 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6749 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6750 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6751 newsrv->conf.file, newsrv->conf.line,
6752 proxy_type_str(curproxy), curproxy->id,
6753 newsrv->id, other_srv->conf.line);
6754 break;
6755 }
6756 }
6757 }
6758
Willy Tarreaudd701652010-05-25 23:03:02 +02006759 /* assign automatic UIDs to servers which don't have one yet */
6760 next_id = 1;
6761 newsrv = curproxy->srv;
6762 while (newsrv != NULL) {
6763 if (!newsrv->puid) {
6764 /* server ID not set, use automatic numbering with first
6765 * spare entry starting with next_svid.
6766 */
6767 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6768 newsrv->conf.id.key = newsrv->puid = next_id;
6769 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6770 }
6771 next_id++;
6772 newsrv = newsrv->next;
6773 }
6774
Willy Tarreau20697042007-11-15 23:26:18 +01006775 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006776 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006777
Willy Tarreau62c3be22012-01-20 13:12:32 +01006778 /*
6779 * If this server supports a maxconn parameter, it needs a dedicated
6780 * tasks to fill the emptied slots when a connection leaves.
6781 * Also, resolve deferred tracking dependency if needed.
6782 */
6783 newsrv = curproxy->srv;
6784 while (newsrv != NULL) {
6785 if (newsrv->minconn > newsrv->maxconn) {
6786 /* Only 'minconn' was specified, or it was higher than or equal
6787 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6788 * this will avoid further useless expensive computations.
6789 */
6790 newsrv->maxconn = newsrv->minconn;
6791 } else if (newsrv->maxconn && !newsrv->minconn) {
6792 /* minconn was not specified, so we set it to maxconn */
6793 newsrv->minconn = newsrv->maxconn;
6794 }
6795
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006796#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006797 if (newsrv->use_ssl || newsrv->check.use_ssl)
6798 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006799#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006800
Willy Tarreau2f075e92013-12-03 11:11:34 +01006801 /* set the check type on the server */
6802 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6803
Willy Tarreau62c3be22012-01-20 13:12:32 +01006804 if (newsrv->trackit) {
6805 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006806 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006807 char *pname, *sname;
6808
6809 pname = newsrv->trackit;
6810 sname = strrchr(pname, '/');
6811
6812 if (sname)
6813 *sname++ = '\0';
6814 else {
6815 sname = pname;
6816 pname = NULL;
6817 }
6818
6819 if (pname) {
6820 px = findproxy(pname, PR_CAP_BE);
6821 if (!px) {
6822 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6823 proxy_type_str(curproxy), curproxy->id,
6824 newsrv->id, pname);
6825 cfgerr++;
6826 goto next_srv;
6827 }
6828 } else
6829 px = curproxy;
6830
6831 srv = findserver(px, sname);
6832 if (!srv) {
6833 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6834 proxy_type_str(curproxy), curproxy->id,
6835 newsrv->id, sname);
6836 cfgerr++;
6837 goto next_srv;
6838 }
6839
Willy Tarreau32091232014-05-16 13:52:00 +02006840 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6841 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6842 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006843 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006844 "tracking as it does not have any check nor agent enabled.\n",
6845 proxy_type_str(curproxy), curproxy->id,
6846 newsrv->id, px->id, srv->id);
6847 cfgerr++;
6848 goto next_srv;
6849 }
6850
6851 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6852
6853 if (loop) {
6854 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6855 "belongs to a tracking chain looping back to %s/%s.\n",
6856 proxy_type_str(curproxy), curproxy->id,
6857 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006858 cfgerr++;
6859 goto next_srv;
6860 }
6861
6862 if (curproxy != px &&
6863 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6864 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6865 "tracking: disable-on-404 option inconsistency.\n",
6866 proxy_type_str(curproxy), curproxy->id,
6867 newsrv->id, px->id, srv->id);
6868 cfgerr++;
6869 goto next_srv;
6870 }
6871
6872 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006873 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006874 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006875 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006876 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006877 }
6878
6879 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006880 newsrv->tracknext = srv->trackers;
6881 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006882
6883 free(newsrv->trackit);
6884 newsrv->trackit = NULL;
6885 }
6886 next_srv:
6887 newsrv = newsrv->next;
6888 }
6889
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006890 /* We have to initialize the server lookup mechanism depending
6891 * on what LB algorithm was choosen.
6892 */
6893
6894 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6895 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6896 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006897 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6898 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6899 init_server_map(curproxy);
6900 } else {
6901 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6902 fwrr_init_server_groups(curproxy);
6903 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006904 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006905
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006906 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006907 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6908 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6909 fwlc_init_server_tree(curproxy);
6910 } else {
6911 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6912 fas_init_server_tree(curproxy);
6913 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006914 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006915
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006916 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006917 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6918 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6919 chash_init_server_tree(curproxy);
6920 } else {
6921 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6922 init_server_map(curproxy);
6923 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006924 break;
6925 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006926
6927 if (curproxy->options & PR_O_LOGASAP)
6928 curproxy->to_log &= ~LW_BYTES;
6929
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006930 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006931 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006932 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6933 proxy_type_str(curproxy), curproxy->id);
6934 err_code |= ERR_WARN;
6935 }
6936
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006937 if (curproxy->mode != PR_MODE_HTTP) {
6938 int optnum;
6939
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006940 if (curproxy->uri_auth) {
6941 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6942 proxy_type_str(curproxy), curproxy->id);
6943 err_code |= ERR_WARN;
6944 curproxy->uri_auth = NULL;
6945 }
6946
Willy Tarreau87cf5142011-08-19 22:57:24 +02006947 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006948 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6949 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6950 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006951 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006952 }
6953
6954 if (curproxy->options & PR_O_ORGTO) {
6955 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6956 "originalto", proxy_type_str(curproxy), curproxy->id);
6957 err_code |= ERR_WARN;
6958 curproxy->options &= ~PR_O_ORGTO;
6959 }
6960
6961 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6962 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6963 (curproxy->cap & cfg_opts[optnum].cap) &&
6964 (curproxy->options & cfg_opts[optnum].val)) {
6965 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6966 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6967 err_code |= ERR_WARN;
6968 curproxy->options &= ~cfg_opts[optnum].val;
6969 }
6970 }
6971
6972 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6973 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6974 (curproxy->cap & cfg_opts2[optnum].cap) &&
6975 (curproxy->options2 & cfg_opts2[optnum].val)) {
6976 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6977 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6978 err_code |= ERR_WARN;
6979 curproxy->options2 &= ~cfg_opts2[optnum].val;
6980 }
6981 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006982
Pieter Baauwd551fb52013-05-08 22:49:23 +02006983#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006984 if (curproxy->conn_src.bind_hdr_occ) {
6985 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006986 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006987 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006988 err_code |= ERR_WARN;
6989 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006990#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006991 }
6992
Willy Tarreaubaaee002006-06-26 02:48:02 +02006993 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006994 * ensure that we're not cross-dressing a TCP server into HTTP.
6995 */
6996 newsrv = curproxy->srv;
6997 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006998 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006999 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7000 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007001 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007002 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007003
Willy Tarreau0cec3312011-10-31 13:49:26 +01007004 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7005 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7006 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7007 err_code |= ERR_WARN;
7008 }
7009
Willy Tarreauc93cd162014-05-13 15:54:22 +02007010 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007011 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7012 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7013 err_code |= ERR_WARN;
7014 }
7015
Pieter Baauwd551fb52013-05-08 22:49:23 +02007016#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007017 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7018 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007019 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 +01007020 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007021 err_code |= ERR_WARN;
7022 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007023#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007024 newsrv = newsrv->next;
7025 }
7026
Willy Tarreau7fc7ebd2014-09-16 16:21:19 +02007027 /* check if we have a frontend with "tcp-request content" looking at L7
7028 * with no inspect-delay
7029 */
7030 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7031 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7032 if (trule->action == TCP_ACT_CAPTURE &&
7033 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7034 break;
7035 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7036 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7037 break;
7038 }
7039
7040 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7041 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7042 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7043 " This means that these rules will randomly find their contents. This can be fixed by"
7044 " setting the tcp-request inspect-delay.\n",
7045 proxy_type_str(curproxy), curproxy->id);
7046 err_code |= ERR_WARN;
7047 }
7048 }
7049
Willy Tarreauc1a21672009-08-16 22:37:44 +02007050 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007051 if (!curproxy->accept)
7052 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007053
Willy Tarreauc1a21672009-08-16 22:37:44 +02007054 if (curproxy->tcp_req.inspect_delay ||
7055 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007056 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007057
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007058 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007059 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007060 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007061 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007062
7063 /* both TCP and HTTP must check switching rules */
7064 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7065 }
7066
7067 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007068 if (curproxy->tcp_req.inspect_delay ||
7069 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7070 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7071
Emeric Brun97679e72010-09-23 17:56:44 +02007072 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7073 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7074
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007075 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007076 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007077 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007078 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007079
7080 /* If the backend does requires RDP cookie persistence, we have to
7081 * enable the corresponding analyser.
7082 */
7083 if (curproxy->options2 & PR_O2_RDPC_PRST)
7084 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7085 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007086 }
7087
7088 /***********************************************************/
7089 /* At this point, target names have already been resolved. */
7090 /***********************************************************/
7091
7092 /* Check multi-process mode compatibility */
7093
7094 if (global.nbproc > 1 && global.stats_fe) {
7095 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7096 unsigned long mask;
7097
7098 mask = nbits(global.nbproc);
7099 if (global.stats_fe->bind_proc)
7100 mask &= global.stats_fe->bind_proc;
7101
7102 if (bind_conf->bind_proc)
7103 mask &= bind_conf->bind_proc;
7104
7105 /* stop here if more than one process is used */
David Carlier6de4c2f2015-07-02 07:00:17 +00007106 if (my_popcountl(mask) > 1)
Willy Tarreau91b00c22014-09-16 13:41:21 +02007107 break;
7108 }
7109 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7110 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");
7111 }
7112 }
7113
7114 /* Make each frontend inherit bind-process from its listeners when not specified. */
7115 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7116 if (curproxy->bind_proc)
7117 continue;
7118
7119 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7120 unsigned long mask;
7121
Willy Tarreau01760ad2015-05-04 21:57:58 +02007122 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007123 curproxy->bind_proc |= mask;
7124 }
7125
7126 if (!curproxy->bind_proc)
Willy Tarreau01760ad2015-05-04 21:57:58 +02007127 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007128 }
7129
7130 if (global.stats_fe) {
7131 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7132 unsigned long mask;
7133
Willy Tarreau01760ad2015-05-04 21:57:58 +02007134 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007135 global.stats_fe->bind_proc |= mask;
7136 }
7137 if (!global.stats_fe->bind_proc)
Willy Tarreau01760ad2015-05-04 21:57:58 +02007138 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007139 }
7140
Willy Tarreaub3228c82014-10-01 20:50:17 +02007141 /* propagate bindings from frontends to backends. Don't do it if there
7142 * are any fatal errors as we must not call it with unresolved proxies.
7143 */
7144 if (!cfgerr) {
7145 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7146 if (curproxy->cap & PR_CAP_FE)
7147 propagate_processes(curproxy, NULL);
7148 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007149 }
7150
7151 /* Bind each unbound backend to all processes when not specified. */
7152 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7153 if (curproxy->bind_proc)
7154 continue;
Willy Tarreau01760ad2015-05-04 21:57:58 +02007155 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007156 }
7157
7158 /*******************************************************/
7159 /* At this step, all proxies have a non-null bind_proc */
7160 /*******************************************************/
7161
7162 /* perform the final checks before creating tasks */
7163
7164 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7165 struct listener *listener;
7166 unsigned int next_id;
7167 int nbproc;
7168
David Carlier6de4c2f2015-07-02 07:00:17 +00007169 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007170
Emeric Brunc52962f2012-11-15 18:28:02 +01007171#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007172 /* Configure SSL for each bind line.
7173 * Note: if configuration fails at some point, the ->ctx member
7174 * remains NULL so that listeners can later detach.
7175 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007176 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007177 int alloc_ctx;
7178
Emeric Brunc52962f2012-11-15 18:28:02 +01007179 if (!bind_conf->is_ssl) {
7180 if (bind_conf->default_ctx) {
7181 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7182 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7183 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007184 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007185 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007186 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007187 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007188 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007189 cfgerr++;
7190 continue;
7191 }
7192
Emeric Brun8dc60392014-05-09 13:52:00 +02007193 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007194 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007195 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7196 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");
7197 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007198 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007199 cfgerr++;
7200 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007201 }
7202
Emeric Brunfc0421f2012-09-07 17:30:07 +02007203 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007204 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007205 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007206#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007207
Willy Tarreaue6b98942007-10-29 01:09:36 +01007208 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007209 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007210 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007211 if (!listener->luid) {
7212 /* listener ID not set, use automatic numbering with first
7213 * spare entry starting with next_luid.
7214 */
7215 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7216 listener->conf.id.key = listener->luid = next_id;
7217 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007218 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007219 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007220
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007221 /* enable separate counters */
7222 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7223 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007224 if (!listener->name)
7225 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007226 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007227
Willy Tarreaue6b98942007-10-29 01:09:36 +01007228 if (curproxy->options & PR_O_TCP_NOLING)
7229 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007230 if (!listener->maxconn)
7231 listener->maxconn = curproxy->maxconn;
7232 if (!listener->backlog)
7233 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007234 if (!listener->maxaccept)
7235 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7236
7237 /* we want to have an optimal behaviour on single process mode to
7238 * maximize the work at once, but in multi-process we want to keep
7239 * some fairness between processes, so we target half of the max
7240 * number of events to be balanced over all the processes the proxy
7241 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7242 * used to disable the limit.
7243 */
7244 if (listener->maxaccept > 0) {
7245 if (nbproc > 1)
7246 listener->maxaccept = (listener->maxaccept + 1) / 2;
7247 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7248 }
7249
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007250 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007251 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007252 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007253 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007254
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007255 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7256 listener->options |= LI_O_TCP_RULES;
7257
Willy Tarreaude3041d2010-05-31 10:56:17 +02007258 if (curproxy->mon_mask.s_addr)
7259 listener->options |= LI_O_CHK_MONNET;
7260
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007261 /* smart accept mode is automatic in HTTP mode */
7262 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007263 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007264 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7265 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007266 }
7267
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007268 /* Release unused SSL configs */
7269 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7270 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007271 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007272#ifdef USE_OPENSSL
7273 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007274 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007275 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007276 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007277 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007278#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007279 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007280
Willy Tarreau102df612014-05-07 23:56:38 +02007281 if (nbproc > 1) {
7282 if (curproxy->uri_auth) {
Willy Tarreau036a83e2014-09-16 15:11:04 +02007283 int count, maxproc = 0;
7284
7285 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carlier6de4c2f2015-07-02 07:00:17 +00007286 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreau036a83e2014-09-16 15:11:04 +02007287 if (count > maxproc)
7288 maxproc = count;
7289 }
7290 /* backends have 0, frontends have 1 or more */
7291 if (maxproc != 1)
7292 Warning("Proxy '%s': in multi-process mode, stats will be"
7293 " limited to process assigned to the current request.\n",
7294 curproxy->id);
7295
Willy Tarreau102df612014-05-07 23:56:38 +02007296 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7297 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7298 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007299 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007300 }
Willy Tarreau102df612014-05-07 23:56:38 +02007301 if (curproxy->appsession_name) {
7302 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7303 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007304 }
Willy Tarreau102df612014-05-07 23:56:38 +02007305 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7306 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7307 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007308 }
7309 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007310
7311 /* create the task associated with the proxy */
7312 curproxy->task = task_new();
7313 if (curproxy->task) {
7314 curproxy->task->context = curproxy;
7315 curproxy->task->process = manage_proxy;
7316 /* no need to queue, it will be done automatically if some
7317 * listener gets limited.
7318 */
7319 curproxy->task->expire = TICK_ETERNITY;
7320 } else {
7321 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7322 curproxy->id);
7323 cfgerr++;
7324 }
Willy Tarreaue56c4f12014-09-16 13:21:03 +02007325 }
7326
Willy Tarreaufbb78422011-06-05 15:38:35 +02007327 /* automatically compute fullconn if not set. We must not do it in the
7328 * loop above because cross-references are not yet fully resolved.
7329 */
7330 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7331 /* If <fullconn> is not set, let's set it to 10% of the sum of
7332 * the possible incoming frontend's maxconns.
7333 */
7334 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7335 struct proxy *fe;
7336 int total = 0;
7337
7338 /* sum up the number of maxconns of frontends which
7339 * reference this backend at least once or which are
7340 * the same one ('listen').
7341 */
7342 for (fe = proxy; fe; fe = fe->next) {
7343 struct switching_rule *rule;
7344 struct hdr_exp *exp;
7345 int found = 0;
7346
7347 if (!(fe->cap & PR_CAP_FE))
7348 continue;
7349
7350 if (fe == curproxy) /* we're on a "listen" instance */
7351 found = 1;
7352
7353 if (fe->defbe.be == curproxy) /* "default_backend" */
7354 found = 1;
7355
7356 /* check if a "use_backend" rule matches */
7357 if (!found) {
7358 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007359 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007360 found = 1;
7361 break;
7362 }
7363 }
7364 }
7365
7366 /* check if a "reqsetbe" rule matches */
7367 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7368 if (exp->action == ACT_SETBE &&
7369 (struct proxy *)exp->replace == curproxy) {
7370 found = 1;
7371 break;
7372 }
7373 }
7374
7375 /* now we've checked all possible ways to reference a backend
7376 * from a frontend.
7377 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007378 if (!found)
7379 continue;
7380 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007381 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007382 /* we have the sum of the maxconns in <total>. We only
7383 * keep 10% of that sum to set the default fullconn, with
7384 * a hard minimum of 1 (to avoid a divide by zero).
7385 */
7386 curproxy->fullconn = (total + 9) / 10;
7387 if (!curproxy->fullconn)
7388 curproxy->fullconn = 1;
7389 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007390 }
7391
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007392 /*
7393 * Recount currently required checks.
7394 */
7395
7396 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7397 int optnum;
7398
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007399 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7400 if (curproxy->options & cfg_opts[optnum].val)
7401 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007402
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007403 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7404 if (curproxy->options2 & cfg_opts2[optnum].val)
7405 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007406 }
7407
Willy Tarreaucdb5e922015-05-01 19:12:05 +02007408 /* compute the required process bindings for the peers */
7409 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
7410 if (curproxy->table.peers.p)
7411 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
7412
Willy Tarreau122541c2011-09-07 21:24:49 +02007413 if (peers) {
7414 struct peers *curpeers = peers, **last;
7415 struct peer *p, *pb;
7416
Willy Tarreauab0419d2015-05-01 19:15:17 +02007417 /* Remove all peers sections which don't have a valid listener,
7418 * which are not used by any table, or which are bound to more
7419 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02007420 */
7421 last = &peers;
7422 while (*last) {
7423 curpeers = *last;
Willy Tarreau34d05b02015-05-01 20:02:17 +02007424
7425 if (curpeers->state == PR_STSTOPPED) {
7426 /* the "disabled" keyword was present */
7427 if (curpeers->peers_fe)
7428 stop_proxy(curpeers->peers_fe);
7429 curpeers->peers_fe = NULL;
7430 }
7431 else if (!curpeers->peers_fe) {
7432 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7433 curpeers->id, localpeer);
7434 }
David Carlier6de4c2f2015-07-02 07:00:17 +00007435 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreauab0419d2015-05-01 19:15:17 +02007436 /* either it's totally stopped or too much used */
7437 if (curpeers->peers_fe->bind_proc) {
7438 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreaua5d7d072015-05-04 21:48:51 +02007439 "running in different processes (%d different ones). "
7440 "Check global.nbproc and all tables' bind-process "
David Carlier6de4c2f2015-07-02 07:00:17 +00007441 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreauab0419d2015-05-01 19:15:17 +02007442 cfgerr++;
7443 }
7444 stop_proxy(curpeers->peers_fe);
7445 curpeers->peers_fe = NULL;
7446 }
Willy Tarreau34d05b02015-05-01 20:02:17 +02007447 else {
Willy Tarreau122541c2011-09-07 21:24:49 +02007448 last = &curpeers->next;
7449 continue;
7450 }
7451
Willy Tarreau34d05b02015-05-01 20:02:17 +02007452 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02007453 p = curpeers->remote;
7454 while (p) {
7455 pb = p->next;
7456 free(p->id);
7457 free(p);
7458 p = pb;
7459 }
7460
7461 /* Destroy and unlink this curpeers section.
7462 * Note: curpeers is backed up into *last.
7463 */
7464 free(curpeers->id);
7465 curpeers = curpeers->next;
7466 free(*last);
7467 *last = curpeers;
7468 }
7469 }
7470
Willy Tarreauf2df7ef2015-05-01 19:09:08 +02007471 /* initialize stick-tables on backend capable proxies. This must not
7472 * be done earlier because the data size may be discovered while parsing
7473 * other proxies.
7474 */
7475 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7476 if (curproxy->state == PR_STSTOPPED)
7477 continue;
7478
7479 if (!stktable_init(&curproxy->table)) {
7480 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7481 cfgerr++;
7482 }
7483 }
7484
Willy Tarreau34eb6712011-10-24 18:15:04 +02007485 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007486 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007487 MEM_F_SHARED);
7488
Willy Tarreaubb925012009-07-23 13:36:36 +02007489 if (cfgerr > 0)
7490 err_code |= ERR_ALERT | ERR_FATAL;
7491 out:
7492 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007493}
7494
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007495/*
7496 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7497 * parsing sessions.
7498 */
7499void cfg_register_keywords(struct cfg_kw_list *kwl)
7500{
7501 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7502}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007503
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007504/*
7505 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7506 */
7507void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7508{
7509 LIST_DEL(&kwl->list);
7510 LIST_INIT(&kwl->list);
7511}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007512
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007513/* this function register new section in the haproxy configuration file.
7514 * <section_name> is the name of this new section and <section_parser>
7515 * is the called parser. If two section declaration have the same name,
7516 * only the first declared is used.
7517 */
7518int cfg_register_section(char *section_name,
7519 int (*section_parser)(const char *, int, char **, int))
7520{
7521 struct cfg_section *cs;
7522
7523 cs = calloc(1, sizeof(*cs));
7524 if (!cs) {
7525 Alert("register section '%s': out of memory.\n", section_name);
7526 return 0;
7527 }
7528
7529 cs->section_name = section_name;
7530 cs->section_parser = section_parser;
7531
7532 LIST_ADDQ(&sections, &cs->list);
7533
7534 return 1;
7535}
7536
Willy Tarreaubaaee002006-06-26 02:48:02 +02007537/*
7538 * Local variables:
7539 * c-indent-level: 8
7540 * c-basic-offset: 8
7541 * End:
7542 */