blob: a423d76294ae76a177727cc30e4d6a2c6e751c5d [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010049#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020050#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051
Willy Tarreaueb0c6142007-05-07 00:53:22 +020052#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010053#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020054#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020055#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020057#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020058#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020059#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020060#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020061#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010062#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020063#include <proto/lb_fwlc.h>
64#include <proto/lb_fwrr.h>
65#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020066#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020068#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010069#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020070#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010071#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010072#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020073#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020074#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020075#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010076#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020077#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020078#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010079#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020080
Emeric Brunfc0421f2012-09-07 17:30:07 +020081#ifdef USE_OPENSSL
82#include <types/ssl_sock.h>
83#include <proto/ssl_sock.h>
84#include <proto/shctx.h>
85#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020086
Willy Tarreauf3c69202006-07-09 16:42:34 +020087/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
88 * ssl-hello-chk option to ensure that the remote server speaks SSL.
89 *
90 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
91 */
92const char sslv3_client_hello_pkt[] = {
93 "\x16" /* ContentType : 0x16 = Hanshake */
94 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
95 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
96 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
97 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
98 "\x03\x00" /* Hello Version : 0x0300 = v3 */
99 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
100 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
101 "\x00" /* Session ID length : empty (no session ID) */
102 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
103 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
104 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
105 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
106 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
107 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
108 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
109 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
110 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
111 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
112 "\x00\x38" "\x00\x39" "\x00\x3A"
113 "\x01" /* Compression Length : 0x01 = 1 byte for types */
114 "\x00" /* Compression Type : 0x00 = NULL compression */
115};
116
Willy Tarreau3842f002009-06-14 11:39:52 +0200117/* various keyword modifiers */
118enum kw_mod {
119 KWM_STD = 0, /* normal */
120 KWM_NO, /* "no" prefixed before the keyword */
121 KWM_DEF, /* "default" prefixed before the keyword */
122};
123
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100124/* permit to store configuration section */
125struct cfg_section {
126 struct list list;
127 char *section_name;
128 int (*section_parser)(const char *, int, char **, int);
129};
130
131/* Used to chain configuration sections definitions. This list
132 * stores struct cfg_section
133 */
134struct list sections = LIST_HEAD_INIT(sections);
135
Willy Tarreau13943ab2006-12-31 00:24:10 +0100136/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100137struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138 const char *name;
139 unsigned int val;
140 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100141 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100142 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100143};
144
145/* proxy->options */
146static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100147{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
149 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
150 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
151 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
152 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
153 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100154 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100155 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
157 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
158 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
159 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
160 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100161#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100162 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100163#else
164 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100165#endif
166
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100167 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100168};
169
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100170/* proxy->options2 */
171static const struct cfg_opt cfg_opts2[] =
172{
173#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100174 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
175 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
176 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100177#else
178 { "splice-request", 0, 0, 0, 0 },
179 { "splice-response", 0, 0, 0, 0 },
180 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100181#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100182 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
183 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
184 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
185 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
186 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
187 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
188 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
189 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
190 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400191 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100192 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200193 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200194 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100195 { NULL, 0, 0, 0 }
196};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200197
Willy Tarreau6daf3432008-01-22 16:44:08 +0100198static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
200int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100201int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200203/* List head of all known configuration keywords */
204static struct cfg_kw_list cfg_keywords = {
205 .list = LIST_HEAD_INIT(cfg_keywords.list)
206};
207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208/*
209 * converts <str> to a list of listeners which are dynamically allocated.
210 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
211 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
212 * - <port> is a numerical port from 1 to 65535 ;
213 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
214 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200215 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
216 * not NULL, it must be a valid pointer to either NULL or a freeable area that
217 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200218 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220{
221 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100222 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 int port, end;
224
225 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200226
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100228 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100229 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
231 str = next;
232 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100233 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234 *next++ = 0;
235 }
236
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100237 ss2 = str2sa_range(str, &port, &end, err,
238 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
239 if (!ss2)
240 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100242 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100243 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200244 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100248 if (!port || !end) {
249 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
250 goto fail;
251 }
252
Emeric Bruned760922010-10-22 17:59:25 +0200253 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200254 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200255 goto fail;
256 }
257
258 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100263 else if (ss2->ss_family == AF_UNSPEC) {
264 socklen_t addr_len;
265
266 /* We want to attach to an already bound fd whose number
267 * is in the addr part of ss2 when cast to sockaddr_in.
268 * Note that by definition there is a single listener.
269 * We still have to determine the address family to
270 * register the correct protocol.
271 */
272 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
273 addr_len = sizeof(*ss2);
274 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
275 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
276 goto fail;
277 }
278
279 port = end = get_host_port(ss2);
280 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100282 /* OK the address looks correct */
283 ss = *ss2;
284
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285 for (; port <= end; port++) {
286 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100287 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200288 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
289 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
290 l->frontend = curproxy;
291 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292
Willy Tarreau40aa0702013-03-10 23:51:38 +0100293 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200295 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100296 l->state = LI_INIT;
297
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100298 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100300 tcpv4_add_listener(l);
301 }
Emeric Bruned760922010-10-22 17:59:25 +0200302 else if (ss.ss_family == AF_INET6) {
303 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
304 tcpv6_add_listener(l);
305 }
306 else {
Emeric Bruned760922010-10-22 17:59:25 +0200307 uxst_add_listener(l);
308 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200309
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200310 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100311 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200312 } /* end for(port) */
313 } /* end while(next) */
314 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200315 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200316 fail:
317 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319}
320
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200321/* Report a warning if a rule is placed after a 'tcp-request content' rule.
322 * Return 1 if the warning has been emitted, otherwise 0.
323 */
324int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
325{
326 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
327 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
328 file, line, arg);
329 return 1;
330 }
331 return 0;
332}
333
Willy Tarreau61d18892009-03-31 10:49:21 +0200334/* Report a warning if a rule is placed after a 'block' rule.
335 * Return 1 if the warning has been emitted, otherwise 0.
336 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100337int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200338{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200339 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200340 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
341 file, line, arg);
342 return 1;
343 }
344 return 0;
345}
346
Willy Tarreau5002f572014-04-23 01:32:02 +0200347/* Report a warning if a rule is placed after an 'http_request' rule.
348 * Return 1 if the warning has been emitted, otherwise 0.
349 */
350int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
351{
352 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
353 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
354 file, line, arg);
355 return 1;
356 }
357 return 0;
358}
359
Willy Tarreau61d18892009-03-31 10:49:21 +0200360/* Report a warning if a rule is placed after a reqrewrite rule.
361 * Return 1 if the warning has been emitted, otherwise 0.
362 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100363int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200364{
365 if (proxy->req_exp) {
366 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
367 file, line, arg);
368 return 1;
369 }
370 return 0;
371}
372
373/* Report a warning if a rule is placed after a reqadd rule.
374 * Return 1 if the warning has been emitted, otherwise 0.
375 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100376int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200377{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100378 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200379 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
380 file, line, arg);
381 return 1;
382 }
383 return 0;
384}
385
386/* Report a warning if a rule is placed after a redirect rule.
387 * Return 1 if the warning has been emitted, otherwise 0.
388 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100389int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200390{
391 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
392 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
393 file, line, arg);
394 return 1;
395 }
396 return 0;
397}
398
399/* Report a warning if a rule is placed after a 'use_backend' rule.
400 * Return 1 if the warning has been emitted, otherwise 0.
401 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
404 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
405 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
406 file, line, arg);
407 return 1;
408 }
409 return 0;
410}
411
Willy Tarreauee445d92014-04-23 01:39:04 +0200412/* Report a warning if a rule is placed after a 'use-server' rule.
413 * Return 1 if the warning has been emitted, otherwise 0.
414 */
415int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
416{
417 if (!LIST_ISEMPTY(&proxy->server_rules)) {
418 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
419 file, line, arg);
420 return 1;
421 }
422 return 0;
423}
424
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200425/* report a warning if a "tcp request connection" rule is dangerously placed */
426int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
427{
428 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
429 warnif_rule_after_block(proxy, file, line, arg) ||
430 warnif_rule_after_http_req(proxy, file, line, arg) ||
431 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
432 warnif_rule_after_reqadd(proxy, file, line, arg) ||
433 warnif_rule_after_redirect(proxy, file, line, arg) ||
434 warnif_rule_after_use_backend(proxy, file, line, arg) ||
435 warnif_rule_after_use_server(proxy, file, line, arg);
436}
437
438/* report a warning if a "tcp request content" rule is dangerously placed */
439int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
440{
441 return warnif_rule_after_block(proxy, file, line, arg) ||
442 warnif_rule_after_http_req(proxy, file, line, arg) ||
443 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
444 warnif_rule_after_reqadd(proxy, file, line, arg) ||
445 warnif_rule_after_redirect(proxy, file, line, arg) ||
446 warnif_rule_after_use_backend(proxy, file, line, arg) ||
447 warnif_rule_after_use_server(proxy, file, line, arg);
448}
449
Willy Tarreau61d18892009-03-31 10:49:21 +0200450/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100451int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200452{
Willy Tarreau5002f572014-04-23 01:32:02 +0200453 return warnif_rule_after_http_req(proxy, file, line, arg) ||
454 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
455 warnif_rule_after_reqadd(proxy, file, line, arg) ||
456 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200457 warnif_rule_after_use_backend(proxy, file, line, arg) ||
458 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200459}
460
461/* report a warning if an http-request rule is dangerously placed */
462int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
463{
Willy Tarreau61d18892009-03-31 10:49:21 +0200464 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
465 warnif_rule_after_reqadd(proxy, file, line, arg) ||
466 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200467 warnif_rule_after_use_backend(proxy, file, line, arg) ||
468 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200469}
470
471/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100472int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200473{
474 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
475 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200476 warnif_rule_after_use_backend(proxy, file, line, arg) ||
477 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200478}
479
480/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100481int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200482{
483 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200484 warnif_rule_after_use_backend(proxy, file, line, arg) ||
485 warnif_rule_after_use_server(proxy, file, line, arg);
486}
487
488/* report a warning if a redirect rule is dangerously placed */
489int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
490{
491 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
492 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200493}
494
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100495/* Report it if a request ACL condition uses some keywords that are incompatible
496 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
497 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
498 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100499 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100500static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100501{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100502 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200503 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100504
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100505 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100506 return 0;
507
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100508 acl = acl_cond_conflicts(cond, where);
509 if (acl) {
510 if (acl->name && *acl->name)
511 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
512 file, line, acl->name, sample_ckp_names(where));
513 else
514 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200515 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100516 return ERR_WARN;
517 }
518 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100519 return 0;
520
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100521 if (acl->name && *acl->name)
522 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200523 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100524 else
525 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200526 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100527 return ERR_WARN;
528}
529
Willy Tarreaubaaee002006-06-26 02:48:02 +0200530/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200531 * parse a line in a <global> section. Returns the error code, 0 if OK, or
532 * any combination of :
533 * - ERR_ABORT: must abort ASAP
534 * - ERR_FATAL: we can continue parsing but not start the service
535 * - ERR_WARN: a warning has been emitted
536 * - ERR_ALERT: an alert has been emitted
537 * Only the two first ones can stop processing, the two others are just
538 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200539 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200540int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200541{
Willy Tarreau058e9072009-07-20 09:30:05 +0200542 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200543 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200544
545 if (!strcmp(args[0], "global")) { /* new section */
546 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200549 else if (!strcmp(args[0], "ca-base")) {
550#ifdef USE_OPENSSL
551 if (global.ca_base != NULL) {
552 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
553 err_code |= ERR_ALERT;
554 goto out;
555 }
556 if (*(args[1]) == 0) {
557 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
558 err_code |= ERR_ALERT | ERR_FATAL;
559 goto out;
560 }
561 global.ca_base = strdup(args[1]);
562#else
563 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
564 err_code |= ERR_ALERT | ERR_FATAL;
565 goto out;
566#endif
567 }
568 else if (!strcmp(args[0], "crt-base")) {
569#ifdef USE_OPENSSL
570 if (global.crt_base != NULL) {
571 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
572 err_code |= ERR_ALERT;
573 goto out;
574 }
575 if (*(args[1]) == 0) {
576 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
577 err_code |= ERR_ALERT | ERR_FATAL;
578 goto out;
579 }
580 global.crt_base = strdup(args[1]);
581#else
582 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
583 err_code |= ERR_ALERT | ERR_FATAL;
584 goto out;
585#endif
586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587 else if (!strcmp(args[0], "daemon")) {
588 global.mode |= MODE_DAEMON;
589 }
590 else if (!strcmp(args[0], "debug")) {
591 global.mode |= MODE_DEBUG;
592 }
593 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100594 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200596 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100597 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200598 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100600 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100602 else if (!strcmp(args[0], "nosplice")) {
603 global.tune.options &= ~GTUNE_USE_SPLICE;
604 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200605 else if (!strcmp(args[0], "nogetaddrinfo")) {
606 global.tune.options &= ~GTUNE_USE_GAI;
607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 else if (!strcmp(args[0], "quiet")) {
609 global.mode |= MODE_QUIET;
610 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200611 else if (!strcmp(args[0], "tune.maxpollevents")) {
612 if (global.tune.maxpollevents != 0) {
613 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200614 err_code |= ERR_ALERT;
615 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200616 }
617 if (*(args[1]) == 0) {
618 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200619 err_code |= ERR_ALERT | ERR_FATAL;
620 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200621 }
622 global.tune.maxpollevents = atol(args[1]);
623 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100624 else if (!strcmp(args[0], "tune.maxaccept")) {
625 if (global.tune.maxaccept != 0) {
626 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200627 err_code |= ERR_ALERT;
628 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100629 }
630 if (*(args[1]) == 0) {
631 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT | ERR_FATAL;
633 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100634 }
635 global.tune.maxaccept = atol(args[1]);
636 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200637 else if (!strcmp(args[0], "tune.chksize")) {
638 if (*(args[1]) == 0) {
639 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
640 err_code |= ERR_ALERT | ERR_FATAL;
641 goto out;
642 }
643 global.tune.chksize = atol(args[1]);
644 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200645#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200646 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
647 global.tune.sslprivatecache = 1;
648 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100649 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200650 if (*(args[1]) == 0) {
651 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT | ERR_FATAL;
653 goto out;
654 }
655 global.tune.sslcachesize = atol(args[1]);
656 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100657 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
658 unsigned int ssllifetime;
659 const char *res;
660
661 if (*(args[1]) == 0) {
662 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
665 }
666
667 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
668 if (res) {
669 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
670 file, linenum, *res, args[0]);
671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
673 }
674
675 global.tune.ssllifetime = ssllifetime;
676 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100677 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
682 }
683 global.tune.ssl_max_record = atol(args[1]);
684 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200685 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
690 }
691 global.tune.ssl_default_dh_param = atol(args[1]);
692 if (global.tune.ssl_default_dh_param < 1024) {
693 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200698#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200699 else if (!strcmp(args[0], "tune.bufsize")) {
700 if (*(args[1]) == 0) {
701 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704 }
705 global.tune.bufsize = atol(args[1]);
706 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
707 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100708 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100709 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200710 }
711 else if (!strcmp(args[0], "tune.maxrewrite")) {
712 if (*(args[1]) == 0) {
713 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
714 err_code |= ERR_ALERT | ERR_FATAL;
715 goto out;
716 }
717 global.tune.maxrewrite = atol(args[1]);
718 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
719 global.tune.maxrewrite = global.tune.bufsize / 2;
720 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100721 else if (!strcmp(args[0], "tune.idletimer")) {
722 unsigned int idle;
723 const char *res;
724
725 if (*(args[1]) == 0) {
726 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
727 err_code |= ERR_ALERT | ERR_FATAL;
728 goto out;
729 }
730
731 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
732 if (res) {
733 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
734 file, linenum, *res, args[0]);
735 err_code |= ERR_ALERT | ERR_FATAL;
736 goto out;
737 }
738
739 if (idle > 65535) {
740 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
743 }
744 global.tune.idle_timer = idle;
745 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100746 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
747 if (global.tune.client_rcvbuf != 0) {
748 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
749 err_code |= ERR_ALERT;
750 goto out;
751 }
752 if (*(args[1]) == 0) {
753 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
754 err_code |= ERR_ALERT | ERR_FATAL;
755 goto out;
756 }
757 global.tune.client_rcvbuf = atol(args[1]);
758 }
759 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
760 if (global.tune.server_rcvbuf != 0) {
761 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
762 err_code |= ERR_ALERT;
763 goto out;
764 }
765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
769 }
770 global.tune.server_rcvbuf = atol(args[1]);
771 }
772 else if (!strcmp(args[0], "tune.sndbuf.client")) {
773 if (global.tune.client_sndbuf != 0) {
774 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
775 err_code |= ERR_ALERT;
776 goto out;
777 }
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
783 global.tune.client_sndbuf = atol(args[1]);
784 }
785 else if (!strcmp(args[0], "tune.sndbuf.server")) {
786 if (global.tune.server_sndbuf != 0) {
787 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
788 err_code |= ERR_ALERT;
789 goto out;
790 }
791 if (*(args[1]) == 0) {
792 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
793 err_code |= ERR_ALERT | ERR_FATAL;
794 goto out;
795 }
796 global.tune.server_sndbuf = atol(args[1]);
797 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200798 else if (!strcmp(args[0], "tune.pipesize")) {
799 if (*(args[1]) == 0) {
800 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
801 err_code |= ERR_ALERT | ERR_FATAL;
802 goto out;
803 }
804 global.tune.pipesize = atol(args[1]);
805 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100806 else if (!strcmp(args[0], "tune.http.cookielen")) {
807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
811 }
812 global.tune.cookie_len = atol(args[1]) + 1;
813 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200814 else if (!strcmp(args[0], "tune.http.maxhdr")) {
815 if (*(args[1]) == 0) {
816 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
817 err_code |= ERR_ALERT | ERR_FATAL;
818 goto out;
819 }
820 global.tune.max_http_hdr = atol(args[1]);
821 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100822 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
823#ifdef USE_ZLIB
824 if (*args[1]) {
825 global.tune.zlibmemlevel = atoi(args[1]);
826 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
827 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
828 file, linenum, args[0]);
829 err_code |= ERR_ALERT | ERR_FATAL;
830 goto out;
831 }
832 } else {
833 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
834 file, linenum, args[0]);
835 err_code |= ERR_ALERT | ERR_FATAL;
836 goto out;
837 }
838#else
839 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
842#endif
843 }
844 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
845#ifdef USE_ZLIB
846 if (*args[1]) {
847 global.tune.zlibwindowsize = atoi(args[1]);
848 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
849 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
850 file, linenum, args[0]);
851 err_code |= ERR_ALERT | ERR_FATAL;
852 goto out;
853 }
854 } else {
855 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
856 file, linenum, args[0]);
857 err_code |= ERR_ALERT | ERR_FATAL;
858 goto out;
859 }
860#else
861 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864#endif
865 }
William Lallemandf3747832012-11-09 12:33:10 +0100866 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
867 if (*args[1]) {
868 global.tune.comp_maxlevel = atoi(args[1]);
869 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
870 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
871 file, linenum, args[0]);
872 err_code |= ERR_ALERT | ERR_FATAL;
873 goto out;
874 }
875 } else {
876 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
877 file, linenum, args[0]);
878 err_code |= ERR_ALERT | ERR_FATAL;
879 goto out;
880 }
881 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882 else if (!strcmp(args[0], "uid")) {
883 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200884 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200885 err_code |= ERR_ALERT;
886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200887 }
888 if (*(args[1]) == 0) {
889 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 }
893 global.uid = atol(args[1]);
894 }
895 else if (!strcmp(args[0], "gid")) {
896 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200897 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200898 err_code |= ERR_ALERT;
899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 }
901 if (*(args[1]) == 0) {
902 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200903 err_code |= ERR_ALERT | ERR_FATAL;
904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200905 }
906 global.gid = atol(args[1]);
907 }
Simon Horman98637e52014-06-20 12:30:16 +0900908 else if (!strcmp(args[0], "external-check")) {
909 global.external_check = 1;
910 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200911 /* user/group name handling */
912 else if (!strcmp(args[0], "user")) {
913 struct passwd *ha_user;
914 if (global.uid != 0) {
915 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200916 err_code |= ERR_ALERT;
917 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200918 }
919 errno = 0;
920 ha_user = getpwnam(args[1]);
921 if (ha_user != NULL) {
922 global.uid = (int)ha_user->pw_uid;
923 }
924 else {
925 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200926 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200927 }
928 }
929 else if (!strcmp(args[0], "group")) {
930 struct group *ha_group;
931 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200932 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200933 err_code |= ERR_ALERT;
934 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200935 }
936 errno = 0;
937 ha_group = getgrnam(args[1]);
938 if (ha_group != NULL) {
939 global.gid = (int)ha_group->gr_gid;
940 }
941 else {
942 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200943 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200944 }
945 }
946 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 if (*(args[1]) == 0) {
949 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200950 err_code |= ERR_ALERT | ERR_FATAL;
951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952 }
953 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100954 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
955 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
956 file, linenum, args[0], LONGBITS, global.nbproc);
957 err_code |= ERR_ALERT | ERR_FATAL;
958 goto out;
959 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200960 }
961 else if (!strcmp(args[0], "maxconn")) {
962 if (global.maxconn != 0) {
963 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200964 err_code |= ERR_ALERT;
965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200966 }
967 if (*(args[1]) == 0) {
968 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200969 err_code |= ERR_ALERT | ERR_FATAL;
970 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200971 }
972 global.maxconn = atol(args[1]);
973#ifdef SYSTEM_MAXCONN
974 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
975 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
976 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200977 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200978 }
979#endif /* SYSTEM_MAXCONN */
980 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200981 else if (!strcmp(args[0], "maxsslconn")) {
982#ifdef USE_OPENSSL
983 if (*(args[1]) == 0) {
984 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
985 err_code |= ERR_ALERT | ERR_FATAL;
986 goto out;
987 }
988 global.maxsslconn = atol(args[1]);
989#else
Emeric Brun0914df82012-10-02 18:45:42 +0200990 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200993#endif
994 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100995 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
996#ifdef USE_OPENSSL
997 if (*(args[1]) == 0) {
998 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
999 err_code |= ERR_ALERT | ERR_FATAL;
1000 goto out;
1001 }
1002 free(global.listen_default_ciphers);
1003 global.listen_default_ciphers = strdup(args[1]);
1004#else
1005 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1006 err_code |= ERR_ALERT | ERR_FATAL;
1007 goto out;
1008#endif
1009 }
1010 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1011#ifdef USE_OPENSSL
1012 if (*(args[1]) == 0) {
1013 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1014 err_code |= ERR_ALERT | ERR_FATAL;
1015 goto out;
1016 }
1017 free(global.connect_default_ciphers);
1018 global.connect_default_ciphers = strdup(args[1]);
1019#else
1020 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1021 err_code |= ERR_ALERT | ERR_FATAL;
1022 goto out;
1023#endif
1024 }
Emeric Brun850efd52014-01-29 12:24:34 +01001025 else if (!strcmp(args[0], "ssl-server-verify")) {
1026 if (*(args[1]) == 0) {
1027 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1028 err_code |= ERR_ALERT | ERR_FATAL;
1029 goto out;
1030 }
1031 if (strcmp(args[1],"none") == 0)
1032 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1033 else if (strcmp(args[1],"required") == 0)
1034 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1035 else {
1036 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1037 err_code |= ERR_ALERT | ERR_FATAL;
1038 goto out;
1039 }
1040 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001041 else if (!strcmp(args[0], "maxconnrate")) {
1042 if (global.cps_lim != 0) {
1043 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1044 err_code |= ERR_ALERT;
1045 goto out;
1046 }
1047 if (*(args[1]) == 0) {
1048 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1049 err_code |= ERR_ALERT | ERR_FATAL;
1050 goto out;
1051 }
1052 global.cps_lim = atol(args[1]);
1053 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001054 else if (!strcmp(args[0], "maxsessrate")) {
1055 if (global.sps_lim != 0) {
1056 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1057 err_code |= ERR_ALERT;
1058 goto out;
1059 }
1060 if (*(args[1]) == 0) {
1061 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1062 err_code |= ERR_ALERT | ERR_FATAL;
1063 goto out;
1064 }
1065 global.sps_lim = atol(args[1]);
1066 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001067 else if (!strcmp(args[0], "maxsslrate")) {
1068 if (global.ssl_lim != 0) {
1069 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1070 err_code |= ERR_ALERT;
1071 goto out;
1072 }
1073 if (*(args[1]) == 0) {
1074 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1075 err_code |= ERR_ALERT | ERR_FATAL;
1076 goto out;
1077 }
1078 global.ssl_lim = atol(args[1]);
1079 }
William Lallemandd85f9172012-11-09 17:05:39 +01001080 else if (!strcmp(args[0], "maxcomprate")) {
1081 if (*(args[1]) == 0) {
1082 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1083 err_code |= ERR_ALERT | ERR_FATAL;
1084 goto out;
1085 }
1086 global.comp_rate_lim = atoi(args[1]) * 1024;
1087 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001088 else if (!strcmp(args[0], "maxpipes")) {
1089 if (global.maxpipes != 0) {
1090 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001091 err_code |= ERR_ALERT;
1092 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001093 }
1094 if (*(args[1]) == 0) {
1095 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001096 err_code |= ERR_ALERT | ERR_FATAL;
1097 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001098 }
1099 global.maxpipes = atol(args[1]);
1100 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001101 else if (!strcmp(args[0], "maxzlibmem")) {
1102 if (*(args[1]) == 0) {
1103 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1104 err_code |= ERR_ALERT | ERR_FATAL;
1105 goto out;
1106 }
William Lallemande3a7d992012-11-20 11:25:20 +01001107 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001108 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001109 else if (!strcmp(args[0], "maxcompcpuusage")) {
1110 if (*(args[1]) == 0) {
1111 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1112 err_code |= ERR_ALERT | ERR_FATAL;
1113 goto out;
1114 }
1115 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001116 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001117 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1118 err_code |= ERR_ALERT | ERR_FATAL;
1119 goto out;
1120 }
1121}
1122
Willy Tarreaubaaee002006-06-26 02:48:02 +02001123 else if (!strcmp(args[0], "ulimit-n")) {
1124 if (global.rlimit_nofile != 0) {
1125 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT;
1127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 }
1129 if (*(args[1]) == 0) {
1130 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001131 err_code |= ERR_ALERT | ERR_FATAL;
1132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001133 }
1134 global.rlimit_nofile = atol(args[1]);
1135 }
1136 else if (!strcmp(args[0], "chroot")) {
1137 if (global.chroot != NULL) {
1138 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001139 err_code |= ERR_ALERT;
1140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 }
1142 if (*(args[1]) == 0) {
1143 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001144 err_code |= ERR_ALERT | ERR_FATAL;
1145 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001146 }
1147 global.chroot = strdup(args[1]);
1148 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001149 else if (!strcmp(args[0], "description")) {
1150 int i, len=0;
1151 char *d;
1152
1153 if (!*args[1]) {
1154 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1155 file, linenum, args[0]);
1156 err_code |= ERR_ALERT | ERR_FATAL;
1157 goto out;
1158 }
1159
Willy Tarreau348acfe2014-04-14 15:00:39 +02001160 for (i = 1; *args[i]; i++)
1161 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001162
1163 if (global.desc)
1164 free(global.desc);
1165
1166 global.desc = d = (char *)calloc(1, len);
1167
Willy Tarreau348acfe2014-04-14 15:00:39 +02001168 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1169 for (i = 2; *args[i]; i++)
1170 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001171 }
1172 else if (!strcmp(args[0], "node")) {
1173 int i;
1174 char c;
1175
1176 for (i=0; args[1][i]; i++) {
1177 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001178 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1179 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001180 break;
1181 }
1182
1183 if (!i || args[1][i]) {
1184 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1185 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1186 file, linenum, args[0]);
1187 err_code |= ERR_ALERT | ERR_FATAL;
1188 goto out;
1189 }
1190
1191 if (global.node)
1192 free(global.node);
1193
1194 global.node = strdup(args[1]);
1195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001196 else if (!strcmp(args[0], "pidfile")) {
1197 if (global.pidfile != NULL) {
1198 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001199 err_code |= ERR_ALERT;
1200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001201 }
1202 if (*(args[1]) == 0) {
1203 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001204 err_code |= ERR_ALERT | ERR_FATAL;
1205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001206 }
1207 global.pidfile = strdup(args[1]);
1208 }
Emeric Bruned760922010-10-22 17:59:25 +02001209 else if (!strcmp(args[0], "unix-bind")) {
1210 int cur_arg = 1;
1211 while (*(args[cur_arg])) {
1212 if (!strcmp(args[cur_arg], "prefix")) {
1213 if (global.unix_bind.prefix != NULL) {
1214 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1215 err_code |= ERR_ALERT;
1216 cur_arg += 2;
1217 continue;
1218 }
1219
1220 if (*(args[cur_arg+1]) == 0) {
1221 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto out;
1224 }
1225 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1226 cur_arg += 2;
1227 continue;
1228 }
1229
1230 if (!strcmp(args[cur_arg], "mode")) {
1231
1232 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1233 cur_arg += 2;
1234 continue;
1235 }
1236
1237 if (!strcmp(args[cur_arg], "uid")) {
1238
1239 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1240 cur_arg += 2;
1241 continue;
1242 }
1243
1244 if (!strcmp(args[cur_arg], "gid")) {
1245
1246 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1247 cur_arg += 2;
1248 continue;
1249 }
1250
1251 if (!strcmp(args[cur_arg], "user")) {
1252 struct passwd *user;
1253
1254 user = getpwnam(args[cur_arg + 1]);
1255 if (!user) {
1256 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1257 file, linenum, args[0], args[cur_arg + 1 ]);
1258 err_code |= ERR_ALERT | ERR_FATAL;
1259 goto out;
1260 }
1261
1262 global.unix_bind.ux.uid = user->pw_uid;
1263 cur_arg += 2;
1264 continue;
1265 }
1266
1267 if (!strcmp(args[cur_arg], "group")) {
1268 struct group *group;
1269
1270 group = getgrnam(args[cur_arg + 1]);
1271 if (!group) {
1272 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1273 file, linenum, args[0], args[cur_arg + 1 ]);
1274 err_code |= ERR_ALERT | ERR_FATAL;
1275 goto out;
1276 }
1277
1278 global.unix_bind.ux.gid = group->gr_gid;
1279 cur_arg += 2;
1280 continue;
1281 }
1282
Willy Tarreaub48f9582011-09-05 01:17:06 +02001283 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001284 file, linenum, args[0]);
1285 err_code |= ERR_ALERT | ERR_FATAL;
1286 goto out;
1287 }
1288 }
William Lallemand0f99e342011-10-12 17:50:54 +02001289 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1290 /* delete previous herited or defined syslog servers */
1291 struct logsrv *back;
1292 struct logsrv *tmp;
1293
1294 if (*(args[1]) != 0) {
1295 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1296 err_code |= ERR_ALERT | ERR_FATAL;
1297 goto out;
1298 }
1299
1300 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1301 LIST_DEL(&tmp->list);
1302 free(tmp);
1303 }
1304 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001305 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001306 struct sockaddr_storage *sk;
1307 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001308 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001309 int arg = 0;
1310 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001311
Willy Tarreaubaaee002006-06-26 02:48:02 +02001312 if (*(args[1]) == 0 || *(args[2]) == 0) {
1313 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001314 err_code |= ERR_ALERT | ERR_FATAL;
1315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001316 }
William Lallemand0f99e342011-10-12 17:50:54 +02001317
1318 logsrv = calloc(1, sizeof(struct logsrv));
1319
Willy Tarreau18324f52014-06-27 18:10:07 +02001320 /* just after the address, a length may be specified */
1321 if (strcmp(args[arg+2], "len") == 0) {
1322 len = atoi(args[arg+3]);
1323 if (len < 80 || len > 65535) {
1324 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1325 file, linenum, args[arg+3]);
1326 err_code |= ERR_ALERT | ERR_FATAL;
1327 goto out;
1328 }
1329 logsrv->maxlen = len;
1330
1331 /* skip these two args */
1332 arg += 2;
1333 }
1334 else
1335 logsrv->maxlen = MAX_SYSLOG_LEN;
1336
1337 if (logsrv->maxlen > global.max_syslog_len) {
1338 global.max_syslog_len = logsrv->maxlen;
1339 logline = realloc(logline, global.max_syslog_len + 1);
1340 }
1341
1342 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001343 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001344 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001345 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001346 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001347 }
1348
William Lallemand0f99e342011-10-12 17:50:54 +02001349 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001350 if (*(args[arg+3])) {
1351 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001352 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001353 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001354 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001355 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001356 }
1357 }
1358
William Lallemand0f99e342011-10-12 17:50:54 +02001359 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001360 if (*(args[arg+4])) {
1361 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001362 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001363 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001364 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001365 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001366 }
1367 }
1368
Willy Tarreau902636f2013-03-10 19:44:48 +01001369 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001370 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001371 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001372 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001373 free(logsrv);
1374 goto out;
1375 }
1376 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001377
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001378 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001379 if (port1 != port2) {
1380 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1381 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001382 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001383 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001384 goto out;
1385 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001386
William Lallemand0f99e342011-10-12 17:50:54 +02001387 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001388 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001389 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001390 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391
William Lallemand0f99e342011-10-12 17:50:54 +02001392 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001393 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001394 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1395 char *name;
1396 int len;
1397
1398 if (global.log_send_hostname != NULL) {
1399 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1400 err_code |= ERR_ALERT;
1401 goto out;
1402 }
1403
1404 if (*(args[1]))
1405 name = args[1];
1406 else
1407 name = hostname;
1408
1409 len = strlen(name);
1410
1411 /* We'll add a space after the name to respect the log format */
1412 free(global.log_send_hostname);
1413 global.log_send_hostname = malloc(len + 2);
1414 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1415 }
Kevinm48936af2010-12-22 16:08:21 +00001416 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1417 if (*(args[1]) == 0) {
1418 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1419 err_code |= ERR_ALERT | ERR_FATAL;
1420 goto out;
1421 }
1422 free(global.log_tag);
1423 global.log_tag = strdup(args[1]);
1424 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001425 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1426 if (global.spread_checks != 0) {
1427 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001428 err_code |= ERR_ALERT;
1429 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001430 }
1431 if (*(args[1]) == 0) {
1432 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001433 err_code |= ERR_ALERT | ERR_FATAL;
1434 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001435 }
1436 global.spread_checks = atol(args[1]);
1437 if (global.spread_checks < 0 || global.spread_checks > 50) {
1438 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001439 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001440 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001441 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001442 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1443 const char *err;
1444 unsigned int val;
1445
1446
1447 if (*(args[1]) == 0) {
1448 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1449 err_code |= ERR_ALERT | ERR_FATAL;
1450 goto out;
1451 }
1452
1453 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1454 if (err) {
1455 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1456 err_code |= ERR_ALERT | ERR_FATAL;
1457 }
1458 global.max_spread_checks = val;
1459 if (global.max_spread_checks < 0) {
1460 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1461 err_code |= ERR_ALERT | ERR_FATAL;
1462 }
1463 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001464 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1465#ifdef USE_CPU_AFFINITY
1466 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001467 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001468 unsigned long cpus = 0;
1469
1470 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001471 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001472 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001473 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001474 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001475 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001476 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001477 proc = atol(args[1]);
1478 if (proc >= 1 && proc <= LONGBITS)
1479 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001480 }
1481
1482 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001483 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1484 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001485 err_code |= ERR_ALERT | ERR_FATAL;
1486 goto out;
1487 }
1488
1489 cur_arg = 2;
1490 while (*args[cur_arg]) {
1491 unsigned int low, high;
1492
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001493 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001494 char *dash = strchr(args[cur_arg], '-');
1495
1496 low = high = str2uic(args[cur_arg]);
1497 if (dash)
1498 high = str2uic(dash + 1);
1499
1500 if (high < low) {
1501 unsigned int swap = low;
1502 low = high;
1503 high = swap;
1504 }
1505
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001506 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001507 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001508 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001509 err_code |= ERR_ALERT | ERR_FATAL;
1510 goto out;
1511 }
1512
1513 while (low <= high)
1514 cpus |= 1UL << low++;
1515 }
1516 else {
1517 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1518 file, linenum, args[0], args[cur_arg]);
1519 err_code |= ERR_ALERT | ERR_FATAL;
1520 goto out;
1521 }
1522 cur_arg++;
1523 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001524 for (i = 0; i < LONGBITS; i++)
1525 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001526 global.cpu_map[i] = cpus;
1527#else
1528 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1529 err_code |= ERR_ALERT | ERR_FATAL;
1530 goto out;
1531#endif
1532 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001533 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001534 struct cfg_kw_list *kwl;
1535 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001536 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001537
1538 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1539 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1540 if (kwl->kw[index].section != CFG_GLOBAL)
1541 continue;
1542 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001543 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001544 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001545 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001546 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001547 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001548 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001549 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001550 err_code |= ERR_WARN;
1551 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001552 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001553 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001554 }
1555 }
1556 }
1557
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001559 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001561
Willy Tarreau058e9072009-07-20 09:30:05 +02001562 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001563 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001564 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565}
1566
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001567void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001569 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 defproxy.mode = PR_MODE_TCP;
1571 defproxy.state = PR_STNEW;
1572 defproxy.maxconn = cfg_maxpconn;
1573 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001574
Simon Horman66183002013-02-23 10:16:43 +09001575 defproxy.defsrv.check.inter = DEF_CHKINTR;
1576 defproxy.defsrv.check.fastinter = 0;
1577 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001578 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1579 defproxy.defsrv.agent.fastinter = 0;
1580 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001581 defproxy.defsrv.check.rise = DEF_RISETIME;
1582 defproxy.defsrv.check.fall = DEF_FALLTIME;
1583 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1584 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001585 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001586 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001587 defproxy.defsrv.maxqueue = 0;
1588 defproxy.defsrv.minconn = 0;
1589 defproxy.defsrv.maxconn = 0;
1590 defproxy.defsrv.slowstart = 0;
1591 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1592 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1593 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001594}
1595
Willy Tarreauade5ec42010-01-28 19:33:49 +01001596
Willy Tarreau63af98d2014-05-18 08:11:41 +02001597/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1598 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1599 * ERR_FATAL in case of error.
1600 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001601static int create_cond_regex_rule(const char *file, int line,
1602 struct proxy *px, int dir, int action, int flags,
1603 const char *cmd, const char *reg, const char *repl,
1604 const char **cond_start)
1605{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001606 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001607 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001608 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001609 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001610 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001611 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001612 int cs;
1613 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001614
1615 if (px == &defproxy) {
1616 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001617 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001618 goto err;
1619 }
1620
1621 if (*reg == 0) {
1622 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001623 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001624 goto err;
1625 }
1626
1627 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001628 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001629
Willy Tarreau5321c422010-01-28 20:35:13 +01001630 if (cond_start &&
1631 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001632 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1633 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1634 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001635 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001636 goto err;
1637 }
1638 }
1639 else if (cond_start && **cond_start) {
1640 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1641 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001642 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001643 goto err;
1644 }
1645
Willy Tarreau63af98d2014-05-18 08:11:41 +02001646 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001647 (dir == SMP_OPT_DIR_REQ) ?
1648 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1649 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1650 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001651
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001652 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001653 if (!preg) {
1654 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001655 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001656 goto err;
1657 }
1658
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001659 cs = !(flags & REG_ICASE);
1660 cap = !(flags & REG_NOSUB);
1661 error = NULL;
1662 if (!regex_comp(reg, preg, cs, cap, &error)) {
1663 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1664 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001665 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001666 goto err;
1667 }
1668
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001669 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001670 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001671 if (repl && err) {
1672 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1673 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001674 ret_code |= ERR_ALERT | ERR_FATAL;
1675 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001676 }
1677
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001678 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001679 ret_code |= ERR_WARN;
1680
1681 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001682
Willy Tarreau63af98d2014-05-18 08:11:41 +02001683 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001684 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001685 err:
1686 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001687 free(errmsg);
1688 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001689}
1690
Willy Tarreaubaaee002006-06-26 02:48:02 +02001691/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001692 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001693 * Returns the error code, 0 if OK, or any combination of :
1694 * - ERR_ABORT: must abort ASAP
1695 * - ERR_FATAL: we can continue parsing but not start the service
1696 * - ERR_WARN: a warning has been emitted
1697 * - ERR_ALERT: an alert has been emitted
1698 * Only the two first ones can stop processing, the two others are just
1699 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001700 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001701int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1702{
1703 static struct peers *curpeers = NULL;
1704 struct peer *newpeer = NULL;
1705 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001706 struct bind_conf *bind_conf;
1707 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001708 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001709 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001710
1711 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001712 if (!*args[1]) {
1713 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001714 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001715 goto out;
1716 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001717
1718 err = invalid_char(args[1]);
1719 if (err) {
1720 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1721 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001722 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001723 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001724 }
1725
1726 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1727 /*
1728 * If there are two proxies with the same name only following
1729 * combinations are allowed:
1730 */
1731 if (strcmp(curpeers->id, args[1]) == 0) {
1732 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1733 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1734 err_code |= ERR_WARN;
1735 }
1736 }
1737
1738 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1739 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1740 err_code |= ERR_ALERT | ERR_ABORT;
1741 goto out;
1742 }
1743
1744 curpeers->next = peers;
1745 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001746 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001747 curpeers->conf.line = linenum;
1748 curpeers->last_change = now.tv_sec;
1749 curpeers->id = strdup(args[1]);
1750 }
1751 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001752 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001753 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001754 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001755
1756 if (!*args[2]) {
1757 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1758 file, linenum, args[0]);
1759 err_code |= ERR_ALERT | ERR_FATAL;
1760 goto out;
1761 }
1762
1763 err = invalid_char(args[1]);
1764 if (err) {
1765 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1766 file, linenum, *err, args[1]);
1767 err_code |= ERR_ALERT | ERR_FATAL;
1768 goto out;
1769 }
1770
1771 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1772 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1773 err_code |= ERR_ALERT | ERR_ABORT;
1774 goto out;
1775 }
1776
1777 /* the peers are linked backwards first */
1778 curpeers->count++;
1779 newpeer->next = curpeers->remote;
1780 curpeers->remote = newpeer;
1781 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001782 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001783 newpeer->conf.line = linenum;
1784
1785 newpeer->last_change = now.tv_sec;
1786 newpeer->id = strdup(args[1]);
1787
Willy Tarreau902636f2013-03-10 19:44:48 +01001788 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001789 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001790 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001791 err_code |= ERR_ALERT | ERR_FATAL;
1792 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001793 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001794
1795 proto = protocol_by_family(sk->ss_family);
1796 if (!proto || !proto->connect) {
1797 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1798 file, linenum, args[0], args[1]);
1799 err_code |= ERR_ALERT | ERR_FATAL;
1800 goto out;
1801 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001802
1803 if (port1 != port2) {
1804 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1805 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001806 err_code |= ERR_ALERT | ERR_FATAL;
1807 goto out;
1808 }
1809
Willy Tarreau2aa38802013-02-20 19:20:59 +01001810 if (!port1) {
1811 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1812 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001813 err_code |= ERR_ALERT | ERR_FATAL;
1814 goto out;
1815 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001816
Emeric Brun32da3c42010-09-23 18:39:19 +02001817 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001818 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001819 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001820 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001821
Emeric Brun32da3c42010-09-23 18:39:19 +02001822 if (strcmp(newpeer->id, localpeer) == 0) {
1823 /* Current is local peer, it define a frontend */
1824 newpeer->local = 1;
1825
1826 if (!curpeers->peers_fe) {
1827 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1828 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1829 err_code |= ERR_ALERT | ERR_ABORT;
1830 goto out;
1831 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001832
Willy Tarreau237250c2011-07-29 01:49:03 +02001833 init_new_proxy(curpeers->peers_fe);
1834 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001835
1836 curpeers->peers_fe->last_change = now.tv_sec;
1837 curpeers->peers_fe->id = strdup(args[1]);
1838 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001839 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001840 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1841 curpeers->peers_fe->timeout.connect = 5000;
1842 curpeers->peers_fe->accept = peer_accept;
1843 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001844 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1845 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001846
1847 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1848
Willy Tarreau902636f2013-03-10 19:44:48 +01001849 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1850 if (errmsg && *errmsg) {
1851 indent_msg(&errmsg, 2);
1852 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001853 }
1854 else
1855 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1856 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001857 err_code |= ERR_FATAL;
1858 goto out;
1859 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001860
1861 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001862 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001863 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1864 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1865 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1866 l->accept = session_accept;
1867 l->handler = process_session;
1868 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1869 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1870 global.maxsock += l->maxconn;
1871 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001872 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001873 else {
1874 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1875 file, linenum, args[0], args[1],
1876 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1877 err_code |= ERR_FATAL;
1878 goto out;
1879 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001880 }
1881 } /* neither "peer" nor "peers" */
1882 else if (*args[0] != 0) {
1883 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1884 err_code |= ERR_ALERT | ERR_FATAL;
1885 goto out;
1886 }
1887
1888out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001889 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001890 return err_code;
1891}
1892
Willy Tarreau3842f002009-06-14 11:39:52 +02001893int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894{
1895 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001896 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001897 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001898 int rc;
1899 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001900 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001901 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001902 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001903 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001904 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001905
Willy Tarreau977b8e42006-12-29 14:19:17 +01001906 if (!strcmp(args[0], "listen"))
1907 rc = PR_CAP_LISTEN;
1908 else if (!strcmp(args[0], "frontend"))
1909 rc = PR_CAP_FE | PR_CAP_RS;
1910 else if (!strcmp(args[0], "backend"))
1911 rc = PR_CAP_BE | PR_CAP_RS;
1912 else if (!strcmp(args[0], "ruleset"))
1913 rc = PR_CAP_RS;
1914 else
1915 rc = PR_CAP_NONE;
1916
1917 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001918 struct ebpt_node *node;
1919
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920 if (!*args[1]) {
1921 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1922 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1923 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001924 err_code |= ERR_ALERT | ERR_ABORT;
1925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001926 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001927
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001928 err = invalid_char(args[1]);
1929 if (err) {
1930 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1931 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001932 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001933 }
1934
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001935 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1936 curproxy = container_of(node, struct proxy, conf.by_name);
1937
1938 if (strcmp(curproxy->id, args[1]) != 0)
1939 break;
1940
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001941 /*
1942 * If there are two proxies with the same name only following
1943 * combinations are allowed:
1944 *
1945 * listen backend frontend ruleset
1946 * listen - - - -
1947 * backend - - OK -
1948 * frontend - OK - -
1949 * ruleset - - - -
1950 */
1951
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001952 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1953 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001954 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1955 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1956 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001957 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001958 }
1959 }
1960
Willy Tarreaubaaee002006-06-26 02:48:02 +02001961 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1962 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001963 err_code |= ERR_ALERT | ERR_ABORT;
1964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001965 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001966
Willy Tarreau97cb7802010-01-03 20:23:58 +01001967 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001968 curproxy->next = proxy;
1969 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001970 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1971 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001972 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001974 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001975 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976
1977 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001978 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001979 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001980
Willy Tarreau4348fad2012-09-20 16:48:07 +02001981 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1982
Willy Tarreau902636f2013-03-10 19:44:48 +01001983 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1984 if (errmsg && *errmsg) {
1985 indent_msg(&errmsg, 2);
1986 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001987 }
1988 else
1989 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1990 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001991 err_code |= ERR_FATAL;
1992 goto out;
1993 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001994
Willy Tarreau4348fad2012-09-20 16:48:07 +02001995 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001996 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001997 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001998 }
1999
2000 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002001 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002002 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002003
Willy Tarreaubaaee002006-06-26 02:48:02 +02002004 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002005 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002006 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002007 curproxy->no_options = defproxy.no_options;
2008 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002009 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002010 curproxy->except_net = defproxy.except_net;
2011 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002012 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002013 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002014
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002015 if (defproxy.fwdfor_hdr_len) {
2016 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2017 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2018 }
2019
Willy Tarreaub86db342009-11-30 11:50:16 +01002020 if (defproxy.orgto_hdr_len) {
2021 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2022 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2023 }
2024
Mark Lamourinec2247f02012-01-04 13:02:01 -05002025 if (defproxy.server_id_hdr_len) {
2026 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2027 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2028 }
2029
Willy Tarreau977b8e42006-12-29 14:19:17 +01002030 if (curproxy->cap & PR_CAP_FE) {
2031 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002032 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002033 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002034
2035 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002036 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2037 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002038
2039 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2040 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041
Willy Tarreau977b8e42006-12-29 14:19:17 +01002042 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002043 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002044 curproxy->fullconn = defproxy.fullconn;
2045 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002046 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002047
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002048 if (defproxy.check_req) {
2049 curproxy->check_req = calloc(1, defproxy.check_len);
2050 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2051 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002052 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002053
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002054 if (defproxy.expect_str) {
2055 curproxy->expect_str = strdup(defproxy.expect_str);
2056 if (defproxy.expect_regex) {
2057 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002058 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2059 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002060 }
2061 }
2062
Willy Tarreau67402132012-05-31 20:40:20 +02002063 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002064 if (defproxy.cookie_name)
2065 curproxy->cookie_name = strdup(defproxy.cookie_name);
2066 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002067 if (defproxy.cookie_domain)
2068 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002069
Willy Tarreau31936852010-10-06 16:59:56 +02002070 if (defproxy.cookie_maxidle)
2071 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2072
2073 if (defproxy.cookie_maxlife)
2074 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2075
Emeric Brun647caf12009-06-30 17:57:00 +02002076 if (defproxy.rdp_cookie_name)
2077 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2078 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2079
Willy Tarreau01732802007-11-01 22:48:15 +01002080 if (defproxy.url_param_name)
2081 curproxy->url_param_name = strdup(defproxy.url_param_name);
2082 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002083
Benoitaffb4812009-03-25 13:02:10 +01002084 if (defproxy.hh_name)
2085 curproxy->hh_name = strdup(defproxy.hh_name);
2086 curproxy->hh_len = defproxy.hh_len;
2087 curproxy->hh_match_domain = defproxy.hh_match_domain;
2088
Willy Tarreauef9a3602012-12-08 22:29:20 +01002089 if (defproxy.conn_src.iface_name)
2090 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2091 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002092 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002093#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002094 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002095#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002096 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002098 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002099 if (defproxy.capture_name)
2100 curproxy->capture_name = strdup(defproxy.capture_name);
2101 curproxy->capture_namelen = defproxy.capture_namelen;
2102 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002103 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104
Willy Tarreau977b8e42006-12-29 14:19:17 +01002105 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002106 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002107 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002108 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002109 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002110 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002111 curproxy->mon_net = defproxy.mon_net;
2112 curproxy->mon_mask = defproxy.mon_mask;
2113 if (defproxy.monitor_uri)
2114 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2115 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002116 if (defproxy.defbe.name)
2117 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002118
2119 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002120 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2121 if (curproxy->conf.logformat_string &&
2122 curproxy->conf.logformat_string != default_http_log_format &&
2123 curproxy->conf.logformat_string != default_tcp_log_format &&
2124 curproxy->conf.logformat_string != clf_http_log_format)
2125 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2126
2127 if (defproxy.conf.lfs_file) {
2128 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2129 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2130 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002131 }
2132
2133 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002134 curproxy->timeout.connect = defproxy.timeout.connect;
2135 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002136 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002137 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002138 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002139 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002140 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002141 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002142 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002143 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002144 }
2145
Willy Tarreaubaaee002006-06-26 02:48:02 +02002146 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002147 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002148
2149 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002150 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002151 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002152 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002153 LIST_INIT(&node->list);
2154 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2155 }
2156
Willy Tarreau62a61232013-04-12 18:13:46 +02002157 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2158 if (curproxy->conf.uniqueid_format_string)
2159 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2160
2161 if (defproxy.conf.uif_file) {
2162 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2163 curproxy->conf.uif_line = defproxy.conf.uif_line;
2164 }
William Lallemanda73203e2012-03-12 12:48:57 +01002165
2166 /* copy default header unique id */
2167 if (defproxy.header_unique_id)
2168 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2169
William Lallemand82fe75c2012-10-23 10:25:10 +02002170 /* default compression options */
2171 if (defproxy.comp != NULL) {
2172 curproxy->comp = calloc(1, sizeof(struct comp));
2173 curproxy->comp->algos = defproxy.comp->algos;
2174 curproxy->comp->types = defproxy.comp->types;
2175 }
2176
Willy Tarreaubaaee002006-06-26 02:48:02 +02002177 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002178 curproxy->conf.used_listener_id = EB_ROOT;
2179 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002180
Simon Horman98637e52014-06-20 12:30:16 +09002181 if (defproxy.check_path)
2182 curproxy->check_path = strdup(defproxy.check_path);
2183 if (defproxy.check_command)
2184 curproxy->check_command = strdup(defproxy.check_command);
2185
Willy Tarreau93893792009-07-23 13:19:11 +02002186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002187 }
2188 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2189 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002190 /* FIXME-20070101: we should do this too at the end of the
2191 * config parsing to free all default values.
2192 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002193 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002194 free(defproxy.check_command);
2195 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002196 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002197 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002198 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002199 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002200 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002201 free(defproxy.capture_name);
2202 free(defproxy.monitor_uri);
2203 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002204 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002205 free(defproxy.fwdfor_hdr_name);
2206 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002207 free(defproxy.orgto_hdr_name);
2208 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002209 free(defproxy.server_id_hdr_name);
2210 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002211 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002212 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002213 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002214 free(defproxy.expect_regex);
2215 defproxy.expect_regex = NULL;
2216 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002217
Willy Tarreau62a61232013-04-12 18:13:46 +02002218 if (defproxy.conf.logformat_string != default_http_log_format &&
2219 defproxy.conf.logformat_string != default_tcp_log_format &&
2220 defproxy.conf.logformat_string != clf_http_log_format)
2221 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002222
Willy Tarreau62a61232013-04-12 18:13:46 +02002223 free(defproxy.conf.uniqueid_format_string);
2224 free(defproxy.conf.lfs_file);
2225 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002226
Willy Tarreaua534fea2008-08-03 12:19:50 +02002227 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002228 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002229
Willy Tarreaubaaee002006-06-26 02:48:02 +02002230 /* we cannot free uri_auth because it might already be used */
2231 init_default_instance();
2232 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002233 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2234 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002235 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002237 }
2238 else if (curproxy == NULL) {
2239 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002240 err_code |= ERR_ALERT | ERR_FATAL;
2241 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002243
2244 /* update the current file and line being parsed */
2245 curproxy->conf.args.file = curproxy->conf.file;
2246 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002247
2248 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002249 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2250 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2251 if (err_code & ERR_FATAL)
2252 goto out;
2253 }
2254 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002255 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002256 int cur_arg;
2257
Willy Tarreaubaaee002006-06-26 02:48:02 +02002258 if (curproxy == &defproxy) {
2259 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002260 err_code |= ERR_ALERT | ERR_FATAL;
2261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002262 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002263 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002264 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265
Willy Tarreau24709282013-03-10 21:32:12 +01002266 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002267 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002268 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002271 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002272
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002273 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002274
2275 /* use default settings for unix sockets */
2276 bind_conf->ux.uid = global.unix_bind.ux.uid;
2277 bind_conf->ux.gid = global.unix_bind.ux.gid;
2278 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002279
2280 /* NOTE: the following line might create several listeners if there
2281 * are comma-separated IPs or port ranges. So all further processing
2282 * will have to be applied to all listeners created after last_listen.
2283 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002284 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2285 if (errmsg && *errmsg) {
2286 indent_msg(&errmsg, 2);
2287 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002288 }
2289 else
2290 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2291 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002292 err_code |= ERR_ALERT | ERR_FATAL;
2293 goto out;
2294 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002295
Willy Tarreau4348fad2012-09-20 16:48:07 +02002296 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2297 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002298 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002299 }
2300
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002301 cur_arg = 2;
2302 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002303 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002304 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002305 char *err;
2306
Willy Tarreau26982662012-09-12 23:17:10 +02002307 kw = bind_find_kw(args[cur_arg]);
2308 if (kw) {
2309 char *err = NULL;
2310 int code;
2311
2312 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002313 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2314 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002315 cur_arg += 1 + kw->skip ;
2316 err_code |= ERR_ALERT | ERR_FATAL;
2317 goto out;
2318 }
2319
Willy Tarreau4348fad2012-09-20 16:48:07 +02002320 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002321 err_code |= code;
2322
2323 if (code) {
2324 if (err && *err) {
2325 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002326 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002327 }
2328 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002329 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2330 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002331 if (code & ERR_FATAL) {
2332 free(err);
2333 cur_arg += 1 + kw->skip;
2334 goto out;
2335 }
2336 }
2337 free(err);
2338 cur_arg += 1 + kw->skip;
2339 continue;
2340 }
2341
Willy Tarreau8638f482012-09-18 18:01:17 +02002342 err = NULL;
2343 if (!bind_dumped) {
2344 bind_dump_kws(&err);
2345 indent_msg(&err, 4);
2346 bind_dumped = 1;
2347 }
2348
2349 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2350 file, linenum, args[0], args[1], args[cur_arg],
2351 err ? " Registered keywords :" : "", err ? err : "");
2352 free(err);
2353
Willy Tarreau93893792009-07-23 13:19:11 +02002354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002356 }
Willy Tarreau93893792009-07-23 13:19:11 +02002357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002358 }
2359 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002360 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2362 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002363 err_code |= ERR_ALERT | ERR_FATAL;
2364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002365 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002366 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002367 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002368
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 /* flush useless bits */
2370 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002373 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002374 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002375 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002376
Willy Tarreau1c47f852006-07-09 08:22:27 +02002377 if (!*args[1]) {
2378 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2379 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002380 err_code |= ERR_ALERT | ERR_FATAL;
2381 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002382 }
2383
Willy Tarreaua534fea2008-08-03 12:19:50 +02002384 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002385 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002386 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002387 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002388 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2389
Willy Tarreau93893792009-07-23 13:19:11 +02002390 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2393 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2394 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2395 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2396 else {
2397 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002398 err_code |= ERR_ALERT | ERR_FATAL;
2399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 }
2401 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002402 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002403 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002404
2405 if (curproxy == &defproxy) {
2406 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2407 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002408 err_code |= ERR_ALERT | ERR_FATAL;
2409 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002410 }
2411
2412 if (!*args[1]) {
2413 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2414 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002417 }
2418
2419 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002420 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002421
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002422 if (curproxy->uuid <= 0) {
2423 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002424 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002425 err_code |= ERR_ALERT | ERR_FATAL;
2426 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002427 }
2428
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002429 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2430 if (node) {
2431 struct proxy *target = container_of(node, struct proxy, conf.id);
2432 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2433 file, linenum, proxy_type_str(curproxy), curproxy->id,
2434 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
2437 }
2438 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002439 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002440 else if (!strcmp(args[0], "description")) {
2441 int i, len=0;
2442 char *d;
2443
Cyril Bonté99ed3272010-01-24 23:29:44 +01002444 if (curproxy == &defproxy) {
2445 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2446 file, linenum, args[0]);
2447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
2449 }
2450
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002451 if (!*args[1]) {
2452 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2453 file, linenum, args[0]);
2454 return -1;
2455 }
2456
Willy Tarreau348acfe2014-04-14 15:00:39 +02002457 for (i = 1; *args[i]; i++)
2458 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002459
2460 d = (char *)calloc(1, len);
2461 curproxy->desc = d;
2462
Willy Tarreau348acfe2014-04-14 15:00:39 +02002463 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2464 for (i = 2; *args[i]; i++)
2465 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002466
2467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002468 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2469 curproxy->state = PR_STSTOPPED;
2470 }
2471 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2472 curproxy->state = PR_STNEW;
2473 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002474 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2475 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002476 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002477
2478 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002479 unsigned int low, high;
2480
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002481 if (strcmp(args[cur_arg], "all") == 0) {
2482 set = 0;
2483 break;
2484 }
2485 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002486 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002487 }
2488 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002489 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002490 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002491 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002492 char *dash = strchr(args[cur_arg], '-');
2493
2494 low = high = str2uic(args[cur_arg]);
2495 if (dash)
2496 high = str2uic(dash + 1);
2497
2498 if (high < low) {
2499 unsigned int swap = low;
2500 low = high;
2501 high = swap;
2502 }
2503
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002504 if (low < 1 || high > LONGBITS) {
2505 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2506 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002507 err_code |= ERR_ALERT | ERR_FATAL;
2508 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002509 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002510 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002511 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002512 }
2513 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002514 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2515 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002516 err_code |= ERR_ALERT | ERR_FATAL;
2517 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002518 }
2519 cur_arg++;
2520 }
2521 curproxy->bind_proc = set;
2522 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002523 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002524 if (curproxy == &defproxy) {
2525 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002526 err_code |= ERR_ALERT | ERR_FATAL;
2527 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002528 }
2529
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002530 err = invalid_char(args[1]);
2531 if (err) {
2532 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2533 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002534 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002535 }
2536
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002537 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002538 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2539 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002542 }
2543 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002544 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2545 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002546
Willy Tarreau977b8e42006-12-29 14:19:17 +01002547 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002548 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002549
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 if (*(args[1]) == 0) {
2551 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2552 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002553 err_code |= ERR_ALERT | ERR_FATAL;
2554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002555 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002556
Willy Tarreau67402132012-05-31 20:40:20 +02002557 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002558 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002559 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002560 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 curproxy->cookie_name = strdup(args[1]);
2562 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002563
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 cur_arg = 2;
2565 while (*(args[cur_arg])) {
2566 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002567 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568 }
2569 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002570 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 }
2572 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002573 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 }
2575 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002576 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 }
2578 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002579 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002581 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002582 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002584 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002585 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002587 else if (!strcmp(args[cur_arg], "httponly")) {
2588 curproxy->ck_opts |= PR_CK_HTTPONLY;
2589 }
2590 else if (!strcmp(args[cur_arg], "secure")) {
2591 curproxy->ck_opts |= PR_CK_SECURE;
2592 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002593 else if (!strcmp(args[cur_arg], "domain")) {
2594 if (!*args[cur_arg + 1]) {
2595 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2596 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002597 err_code |= ERR_ALERT | ERR_FATAL;
2598 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002599 }
2600
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002601 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002602 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002603 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2604 " dots nor does not start with a dot."
2605 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002606 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002607 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002608 }
2609
2610 err = invalid_domainchar(args[cur_arg + 1]);
2611 if (err) {
2612 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2613 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002616 }
2617
Willy Tarreau68a897b2009-12-03 23:28:34 +01002618 if (!curproxy->cookie_domain) {
2619 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2620 } else {
2621 /* one domain was already specified, add another one by
2622 * building the string which will be returned along with
2623 * the cookie.
2624 */
2625 char *new_ptr;
2626 int new_len = strlen(curproxy->cookie_domain) +
2627 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2628 new_ptr = malloc(new_len);
2629 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2630 free(curproxy->cookie_domain);
2631 curproxy->cookie_domain = new_ptr;
2632 }
Willy Tarreau31936852010-10-06 16:59:56 +02002633 cur_arg++;
2634 }
2635 else if (!strcmp(args[cur_arg], "maxidle")) {
2636 unsigned int maxidle;
2637 const char *res;
2638
2639 if (!*args[cur_arg + 1]) {
2640 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2641 file, linenum, args[cur_arg]);
2642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
2644 }
2645
2646 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2647 if (res) {
2648 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2649 file, linenum, *res, args[cur_arg]);
2650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
2652 }
2653 curproxy->cookie_maxidle = maxidle;
2654 cur_arg++;
2655 }
2656 else if (!strcmp(args[cur_arg], "maxlife")) {
2657 unsigned int maxlife;
2658 const char *res;
2659
2660 if (!*args[cur_arg + 1]) {
2661 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2662 file, linenum, args[cur_arg]);
2663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
2665 }
2666
2667 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2668 if (res) {
2669 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2670 file, linenum, *res, args[cur_arg]);
2671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
2673 }
2674 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002675 cur_arg++;
2676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002677 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002678 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002680 err_code |= ERR_ALERT | ERR_FATAL;
2681 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002682 }
2683 cur_arg++;
2684 }
Willy Tarreau67402132012-05-31 20:40:20 +02002685 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002686 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2687 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002688 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002689 }
2690
Willy Tarreau67402132012-05-31 20:40:20 +02002691 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2693 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002695 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002696
Willy Tarreau67402132012-05-31 20:40:20 +02002697 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002698 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2699 file, linenum);
2700 err_code |= ERR_ALERT | ERR_FATAL;
2701 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002702 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman98637e52014-06-20 12:30:16 +09002703 else if (!strcmp(args[0], "external-check")) {
2704 if (*(args[1]) == 0) {
2705 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2706 file, linenum, args[0]);
2707 err_code |= ERR_ALERT | ERR_FATAL;
2708 goto out;
2709 }
2710
2711 if (!strcmp(args[1], "command")) {
2712 if (*(args[1]) == 0) {
2713 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2714 file, linenum, args[1]);
2715 err_code |= ERR_ALERT | ERR_FATAL;
2716 goto out;
2717 }
2718 free(curproxy->check_command);
2719 curproxy->check_command = strdup(args[2]);
2720 }
2721 else if (!strcmp(args[1], "path")) {
2722 if (*(args[1]) == 0) {
2723 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2724 file, linenum, args[1]);
2725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
2727 }
2728 free(curproxy->check_path);
2729 curproxy->check_path = strdup(args[2]);
2730 }
2731 else {
2732 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
2733 file, linenum, args[1]);
2734 err_code |= ERR_ALERT | ERR_FATAL;
2735 goto out;
2736 }
2737 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002738 else if (!strcmp(args[0], "persist")) { /* persist */
2739 if (*(args[1]) == 0) {
2740 Alert("parsing [%s:%d] : missing persist method.\n",
2741 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002742 err_code |= ERR_ALERT | ERR_FATAL;
2743 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002744 }
2745
2746 if (!strncmp(args[1], "rdp-cookie", 10)) {
2747 curproxy->options2 |= PR_O2_RDPC_PRST;
2748
Emeric Brunb982a3d2010-01-04 15:45:53 +01002749 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002750 const char *beg, *end;
2751
2752 beg = args[1] + 11;
2753 end = strchr(beg, ')');
2754
2755 if (!end || end == beg) {
2756 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2757 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002760 }
2761
2762 free(curproxy->rdp_cookie_name);
2763 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2764 curproxy->rdp_cookie_len = end-beg;
2765 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002766 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002767 free(curproxy->rdp_cookie_name);
2768 curproxy->rdp_cookie_name = strdup("msts");
2769 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2770 }
2771 else { /* syntax */
2772 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2773 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002774 err_code |= ERR_ALERT | ERR_FATAL;
2775 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002776 }
2777 }
2778 else {
2779 Alert("parsing [%s:%d] : unknown persist method.\n",
2780 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002781 err_code |= ERR_ALERT | ERR_FATAL;
2782 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002783 }
2784 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002785 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002786 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002787
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002788 if (curproxy == &defproxy) {
2789 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
2792 }
2793
Willy Tarreau977b8e42006-12-29 14:19:17 +01002794 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002795 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002796
Willy Tarreaubaaee002006-06-26 02:48:02 +02002797 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002798 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002799 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002800 err_code |= ERR_ALERT | ERR_FATAL;
2801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002802 }
2803 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002804 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002805 curproxy->appsession_name = strdup(args[1]);
2806 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2807 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002808 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2809 if (err) {
2810 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2811 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002812 err_code |= ERR_ALERT | ERR_FATAL;
2813 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002814 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002815 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002816
Willy Tarreau51041c72007-09-09 21:56:53 +02002817 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2818 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002819 err_code |= ERR_ALERT | ERR_ABORT;
2820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002821 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002822
2823 cur_arg = 6;
2824 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002825 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2826 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002827 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002828 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002829 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002830 } else if (!strcmp(args[cur_arg], "prefix")) {
2831 curproxy->options2 |= PR_O2_AS_PFX;
2832 } else if (!strcmp(args[cur_arg], "mode")) {
2833 if (!*args[cur_arg + 1]) {
2834 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2835 file, linenum, args[0], args[cur_arg]);
2836 err_code |= ERR_ALERT | ERR_FATAL;
2837 goto out;
2838 }
2839
2840 cur_arg++;
2841 if (!strcmp(args[cur_arg], "query-string")) {
2842 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2843 curproxy->options2 |= PR_O2_AS_M_QS;
2844 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2845 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2846 curproxy->options2 |= PR_O2_AS_M_PP;
2847 } else {
2848 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
2851 }
2852 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002853 cur_arg++;
2854 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855 } /* Url App Session */
2856 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002857 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002858 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002859
Willy Tarreaubaaee002006-06-26 02:48:02 +02002860 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002861 if (curproxy == &defproxy) {
2862 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2863 err_code |= ERR_ALERT | ERR_FATAL;
2864 goto out;
2865 }
2866
Willy Tarreaubaaee002006-06-26 02:48:02 +02002867 if (*(args[4]) == 0) {
2868 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2869 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002870 err_code |= ERR_ALERT | ERR_FATAL;
2871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002873 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002874 curproxy->capture_name = strdup(args[2]);
2875 curproxy->capture_namelen = strlen(curproxy->capture_name);
2876 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002877 curproxy->to_log |= LW_COOKIE;
2878 }
2879 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2880 struct cap_hdr *hdr;
2881
2882 if (curproxy == &defproxy) {
2883 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002886 }
2887
2888 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2889 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2890 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002891 err_code |= ERR_ALERT | ERR_FATAL;
2892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002893 }
2894
2895 hdr = calloc(sizeof(struct cap_hdr), 1);
2896 hdr->next = curproxy->req_cap;
2897 hdr->name = strdup(args[3]);
2898 hdr->namelen = strlen(args[3]);
2899 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002900 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002901 hdr->index = curproxy->nb_req_cap++;
2902 curproxy->req_cap = hdr;
2903 curproxy->to_log |= LW_REQHDR;
2904 }
2905 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2906 struct cap_hdr *hdr;
2907
2908 if (curproxy == &defproxy) {
2909 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002910 err_code |= ERR_ALERT | ERR_FATAL;
2911 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912 }
2913
2914 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2915 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2916 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002917 err_code |= ERR_ALERT | ERR_FATAL;
2918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002919 }
2920 hdr = calloc(sizeof(struct cap_hdr), 1);
2921 hdr->next = curproxy->rsp_cap;
2922 hdr->name = strdup(args[3]);
2923 hdr->namelen = strlen(args[3]);
2924 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002925 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002926 hdr->index = curproxy->nb_rsp_cap++;
2927 curproxy->rsp_cap = hdr;
2928 curproxy->to_log |= LW_RSPHDR;
2929 }
2930 else {
2931 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2932 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002933 err_code |= ERR_ALERT | ERR_FATAL;
2934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002935 }
2936 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002937 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002938 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002939 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002940
Willy Tarreaubaaee002006-06-26 02:48:02 +02002941 if (*(args[1]) == 0) {
2942 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2943 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002944 err_code |= ERR_ALERT | ERR_FATAL;
2945 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002946 }
2947 curproxy->conn_retries = atol(args[1]);
2948 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002949 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002950 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002951
2952 if (curproxy == &defproxy) {
2953 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2954 err_code |= ERR_ALERT | ERR_FATAL;
2955 goto out;
2956 }
2957
Willy Tarreau20b0de52012-12-24 15:45:22 +01002958 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2959 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2960 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2961 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002962 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002963 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2964 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002965 file, linenum, args[0]);
2966 err_code |= ERR_WARN;
2967 }
2968
Willy Tarreauff011f22011-01-06 17:51:27 +01002969 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002970
Willy Tarreauff011f22011-01-06 17:51:27 +01002971 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002972 err_code |= ERR_ALERT | ERR_ABORT;
2973 goto out;
2974 }
2975
Willy Tarreau5002f572014-04-23 01:32:02 +02002976 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002977 err_code |= warnif_cond_conflicts(rule->cond,
2978 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2979 file, linenum);
2980
Willy Tarreauff011f22011-01-06 17:51:27 +01002981 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002982 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002983 else if (!strcmp(args[0], "http-response")) { /* response access control */
2984 struct http_res_rule *rule;
2985
2986 if (curproxy == &defproxy) {
2987 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
2990 }
2991
2992 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2993 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2994 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2995 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2996 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2997 file, linenum, args[0]);
2998 err_code |= ERR_WARN;
2999 }
3000
3001 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3002
3003 if (!rule) {
3004 err_code |= ERR_ALERT | ERR_ABORT;
3005 goto out;
3006 }
3007
3008 err_code |= warnif_cond_conflicts(rule->cond,
3009 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3010 file, linenum);
3011
3012 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3013 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003014 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3015 /* set the header name and length into the proxy structure */
3016 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3017 err_code |= ERR_WARN;
3018
3019 if (!*args[1]) {
3020 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3021 file, linenum, args[0]);
3022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
3024 }
3025
3026 /* set the desired header name */
3027 free(curproxy->server_id_hdr_name);
3028 curproxy->server_id_hdr_name = strdup(args[1]);
3029 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3030 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003031 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003032 struct http_req_rule *rule;
3033
Willy Tarreaub099aca2008-10-12 17:26:37 +02003034 if (curproxy == &defproxy) {
3035 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003038 }
3039
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003040 /* emulate "block" using "http-request block". Since these rules are supposed to
3041 * be processed before all http-request rules, we put them into their own list
3042 * and will insert them at the end.
3043 */
3044 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3045 if (!rule) {
3046 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003047 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003048 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003049 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3050 err_code |= warnif_cond_conflicts(rule->cond,
3051 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3052 file, linenum);
3053 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003054
3055 if (!already_warned(WARN_BLOCK_DEPRECATED))
3056 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of 'http-request deny' which uses the exact same syntax. The rules are translated but support might disappear in a future version.\n", file, linenum, args[0]);
3057
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003058 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003059 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003060 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003061
Cyril Bonté99ed3272010-01-24 23:29:44 +01003062 if (curproxy == &defproxy) {
3063 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
3066 }
3067
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003068 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003069 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3070 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003073 }
3074
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003075 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003076 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003077 err_code |= warnif_cond_conflicts(rule->cond,
3078 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3079 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003080 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003081 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003082 struct switching_rule *rule;
3083
Willy Tarreaub099aca2008-10-12 17:26:37 +02003084 if (curproxy == &defproxy) {
3085 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003086 err_code |= ERR_ALERT | ERR_FATAL;
3087 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003088 }
3089
Willy Tarreau55ea7572007-06-17 19:56:27 +02003090 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003091 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003092
3093 if (*(args[1]) == 0) {
3094 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003095 err_code |= ERR_ALERT | ERR_FATAL;
3096 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003097 }
3098
Willy Tarreauf51658d2014-04-23 01:21:56 +02003099 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3100 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3101 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3102 file, linenum, errmsg);
3103 err_code |= ERR_ALERT | ERR_FATAL;
3104 goto out;
3105 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003106
Willy Tarreauf51658d2014-04-23 01:21:56 +02003107 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003108 }
3109
3110 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3111 rule->cond = cond;
3112 rule->be.name = strdup(args[1]);
3113 LIST_INIT(&rule->list);
3114 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3115 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003116 else if (strcmp(args[0], "use-server") == 0) {
3117 struct server_rule *rule;
3118
3119 if (curproxy == &defproxy) {
3120 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3121 err_code |= ERR_ALERT | ERR_FATAL;
3122 goto out;
3123 }
3124
3125 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3126 err_code |= ERR_WARN;
3127
3128 if (*(args[1]) == 0) {
3129 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3130 err_code |= ERR_ALERT | ERR_FATAL;
3131 goto out;
3132 }
3133
3134 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3135 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3136 file, linenum, args[0]);
3137 err_code |= ERR_ALERT | ERR_FATAL;
3138 goto out;
3139 }
3140
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003141 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3142 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3143 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003144 err_code |= ERR_ALERT | ERR_FATAL;
3145 goto out;
3146 }
3147
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003148 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003149
3150 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3151 rule->cond = cond;
3152 rule->srv.name = strdup(args[1]);
3153 LIST_INIT(&rule->list);
3154 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3155 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3156 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003157 else if ((!strcmp(args[0], "force-persist")) ||
3158 (!strcmp(args[0], "ignore-persist"))) {
3159 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003160
3161 if (curproxy == &defproxy) {
3162 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
3165 }
3166
3167 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3168 err_code |= ERR_WARN;
3169
Willy Tarreauef6494c2010-01-28 17:12:36 +01003170 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003171 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3172 file, linenum, args[0]);
3173 err_code |= ERR_ALERT | ERR_FATAL;
3174 goto out;
3175 }
3176
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003177 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3178 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3179 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
3182 }
3183
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003184 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3185 * where force-persist is applied.
3186 */
3187 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003188
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003189 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003190 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003191 if (!strcmp(args[0], "force-persist")) {
3192 rule->type = PERSIST_TYPE_FORCE;
3193 } else {
3194 rule->type = PERSIST_TYPE_IGNORE;
3195 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003196 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003197 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003198 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003199 else if (!strcmp(args[0], "stick-table")) {
3200 int myidx = 1;
3201
Emeric Brun32da3c42010-09-23 18:39:19 +02003202 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003203 curproxy->table.type = (unsigned int)-1;
3204 while (*args[myidx]) {
3205 const char *err;
3206
3207 if (strcmp(args[myidx], "size") == 0) {
3208 myidx++;
3209 if (!*(args[myidx])) {
3210 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3211 file, linenum, args[myidx-1]);
3212 err_code |= ERR_ALERT | ERR_FATAL;
3213 goto out;
3214 }
3215 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3216 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3217 file, linenum, *err, args[myidx-1]);
3218 err_code |= ERR_ALERT | ERR_FATAL;
3219 goto out;
3220 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003221 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003222 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003223 else if (strcmp(args[myidx], "peers") == 0) {
3224 myidx++;
Godbach50523162013-12-11 19:48:57 +08003225 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003226 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3227 file, linenum, args[myidx-1]);
3228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
Godbach50523162013-12-11 19:48:57 +08003230 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003231 curproxy->table.peers.name = strdup(args[myidx++]);
3232 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003233 else if (strcmp(args[myidx], "expire") == 0) {
3234 myidx++;
3235 if (!*(args[myidx])) {
3236 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3237 file, linenum, args[myidx-1]);
3238 err_code |= ERR_ALERT | ERR_FATAL;
3239 goto out;
3240 }
3241 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3242 if (err) {
3243 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3244 file, linenum, *err, args[myidx-1]);
3245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
3247 }
3248 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003249 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003250 }
3251 else if (strcmp(args[myidx], "nopurge") == 0) {
3252 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003253 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003254 }
3255 else if (strcmp(args[myidx], "type") == 0) {
3256 myidx++;
3257 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3258 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3259 file, linenum, args[myidx]);
3260 err_code |= ERR_ALERT | ERR_FATAL;
3261 goto out;
3262 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003263 /* myidx already points to next arg */
3264 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003265 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003266 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003267 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003268
3269 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003270 nw = args[myidx];
3271 while (*nw) {
3272 /* the "store" keyword supports a comma-separated list */
3273 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003274 sa = NULL; /* store arg */
3275 while (*nw && *nw != ',') {
3276 if (*nw == '(') {
3277 *nw = 0;
3278 sa = ++nw;
3279 while (*nw != ')') {
3280 if (!*nw) {
3281 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3282 file, linenum, args[0], cw);
3283 err_code |= ERR_ALERT | ERR_FATAL;
3284 goto out;
3285 }
3286 nw++;
3287 }
3288 *nw = '\0';
3289 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003290 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003291 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003292 if (*nw)
3293 *nw++ = '\0';
3294 type = stktable_get_data_type(cw);
3295 if (type < 0) {
3296 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3297 file, linenum, args[0], cw);
3298 err_code |= ERR_ALERT | ERR_FATAL;
3299 goto out;
3300 }
Willy Tarreauac782882010-06-20 10:41:54 +02003301
3302 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3303 switch (err) {
3304 case PE_NONE: break;
3305 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003306 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3307 file, linenum, args[0], cw);
3308 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003309 break;
3310
3311 case PE_ARG_MISSING:
3312 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3313 file, linenum, args[0], cw);
3314 err_code |= ERR_ALERT | ERR_FATAL;
3315 goto out;
3316
3317 case PE_ARG_NOT_USED:
3318 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3319 file, linenum, args[0], cw);
3320 err_code |= ERR_ALERT | ERR_FATAL;
3321 goto out;
3322
3323 default:
3324 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3325 file, linenum, args[0], cw);
3326 err_code |= ERR_ALERT | ERR_FATAL;
3327 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003328 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003329 }
3330 myidx++;
3331 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003332 else {
3333 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3334 file, linenum, args[myidx]);
3335 err_code |= ERR_ALERT | ERR_FATAL;
3336 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003337 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003338 }
3339
3340 if (!curproxy->table.size) {
3341 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3342 file, linenum);
3343 err_code |= ERR_ALERT | ERR_FATAL;
3344 goto out;
3345 }
3346
3347 if (curproxy->table.type == (unsigned int)-1) {
3348 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3349 file, linenum);
3350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
3352 }
3353 }
3354 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003355 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003356 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003357 int myidx = 0;
3358 const char *name = NULL;
3359 int flags;
3360
3361 if (curproxy == &defproxy) {
3362 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3363 err_code |= ERR_ALERT | ERR_FATAL;
3364 goto out;
3365 }
3366
3367 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3368 err_code |= ERR_WARN;
3369 goto out;
3370 }
3371
3372 myidx++;
3373 if ((strcmp(args[myidx], "store") == 0) ||
3374 (strcmp(args[myidx], "store-request") == 0)) {
3375 myidx++;
3376 flags = STK_IS_STORE;
3377 }
3378 else if (strcmp(args[myidx], "store-response") == 0) {
3379 myidx++;
3380 flags = STK_IS_STORE | STK_ON_RSP;
3381 }
3382 else if (strcmp(args[myidx], "match") == 0) {
3383 myidx++;
3384 flags = STK_IS_MATCH;
3385 }
3386 else if (strcmp(args[myidx], "on") == 0) {
3387 myidx++;
3388 flags = STK_IS_MATCH | STK_IS_STORE;
3389 }
3390 else {
3391 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3392 err_code |= ERR_ALERT | ERR_FATAL;
3393 goto out;
3394 }
3395
3396 if (*(args[myidx]) == 0) {
3397 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3398 err_code |= ERR_ALERT | ERR_FATAL;
3399 goto out;
3400 }
3401
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003402 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003403 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003404 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003405 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
3408 }
3409
3410 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003411 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3412 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3413 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003414 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003415 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003416 goto out;
3417 }
3418 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003419 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3420 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3421 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003422 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003423 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003424 goto out;
3425 }
3426 }
3427
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003428 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003429 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003430
Emeric Brunb982a3d2010-01-04 15:45:53 +01003431 if (strcmp(args[myidx], "table") == 0) {
3432 myidx++;
3433 name = args[myidx++];
3434 }
3435
Willy Tarreauef6494c2010-01-28 17:12:36 +01003436 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003437 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3438 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3439 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003440 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003441 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003442 goto out;
3443 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003444 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003445 else if (*(args[myidx])) {
3446 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3447 file, linenum, args[0], args[myidx]);
3448 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003449 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003450 goto out;
3451 }
Emeric Brun97679e72010-09-23 17:56:44 +02003452 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003453 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003454 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003455 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003456
Emeric Brunb982a3d2010-01-04 15:45:53 +01003457 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3458 rule->cond = cond;
3459 rule->expr = expr;
3460 rule->flags = flags;
3461 rule->table.name = name ? strdup(name) : NULL;
3462 LIST_INIT(&rule->list);
3463 if (flags & STK_ON_RSP)
3464 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3465 else
3466 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003468 else if (!strcmp(args[0], "stats")) {
3469 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3470 curproxy->uri_auth = NULL; /* we must detach from the default config */
3471
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003472 if (!*args[1]) {
3473 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003474 } else if (!strcmp(args[1], "admin")) {
3475 struct stats_admin_rule *rule;
3476
3477 if (curproxy == &defproxy) {
3478 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3479 err_code |= ERR_ALERT | ERR_FATAL;
3480 goto out;
3481 }
3482
3483 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3484 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3485 err_code |= ERR_ALERT | ERR_ABORT;
3486 goto out;
3487 }
3488
3489 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3490 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3491 file, linenum, args[0], args[1]);
3492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
3494 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003495 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3496 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3497 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
3500 }
3501
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003502 err_code |= warnif_cond_conflicts(cond,
3503 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3504 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003505
3506 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3507 rule->cond = cond;
3508 LIST_INIT(&rule->list);
3509 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003510 } else if (!strcmp(args[1], "uri")) {
3511 if (*(args[2]) == 0) {
3512 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003513 err_code |= ERR_ALERT | ERR_FATAL;
3514 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003515 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3516 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003517 err_code |= ERR_ALERT | ERR_ABORT;
3518 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003519 }
3520 } else if (!strcmp(args[1], "realm")) {
3521 if (*(args[2]) == 0) {
3522 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003523 err_code |= ERR_ALERT | ERR_FATAL;
3524 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003525 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3526 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003527 err_code |= ERR_ALERT | ERR_ABORT;
3528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003529 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003530 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003531 unsigned interval;
3532
3533 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3534 if (err) {
3535 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3536 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003537 err_code |= ERR_ALERT | ERR_FATAL;
3538 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003539 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3540 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003541 err_code |= ERR_ALERT | ERR_ABORT;
3542 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003543 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003544 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003545 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003546
3547 if (curproxy == &defproxy) {
3548 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3549 err_code |= ERR_ALERT | ERR_FATAL;
3550 goto out;
3551 }
3552
3553 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3554 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3555 err_code |= ERR_ALERT | ERR_ABORT;
3556 goto out;
3557 }
3558
Willy Tarreauff011f22011-01-06 17:51:27 +01003559 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3560 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003561 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3562 file, linenum, args[0]);
3563 err_code |= ERR_WARN;
3564 }
3565
Willy Tarreauff011f22011-01-06 17:51:27 +01003566 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003567
Willy Tarreauff011f22011-01-06 17:51:27 +01003568 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003569 err_code |= ERR_ALERT | ERR_ABORT;
3570 goto out;
3571 }
3572
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003573 err_code |= warnif_cond_conflicts(rule->cond,
3574 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3575 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003576 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003577
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 } else if (!strcmp(args[1], "auth")) {
3579 if (*(args[2]) == 0) {
3580 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003581 err_code |= ERR_ALERT | ERR_FATAL;
3582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003583 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3584 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003585 err_code |= ERR_ALERT | ERR_ABORT;
3586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003587 }
3588 } else if (!strcmp(args[1], "scope")) {
3589 if (*(args[2]) == 0) {
3590 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003591 err_code |= ERR_ALERT | ERR_FATAL;
3592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3594 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003595 err_code |= ERR_ALERT | ERR_ABORT;
3596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003597 }
3598 } else if (!strcmp(args[1], "enable")) {
3599 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3600 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003601 err_code |= ERR_ALERT | ERR_ABORT;
3602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003603 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003604 } else if (!strcmp(args[1], "hide-version")) {
3605 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3606 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003607 err_code |= ERR_ALERT | ERR_ABORT;
3608 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003609 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003610 } else if (!strcmp(args[1], "show-legends")) {
3611 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3612 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3613 err_code |= ERR_ALERT | ERR_ABORT;
3614 goto out;
3615 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003616 } else if (!strcmp(args[1], "show-node")) {
3617
3618 if (*args[2]) {
3619 int i;
3620 char c;
3621
3622 for (i=0; args[2][i]; i++) {
3623 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003624 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3625 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003626 break;
3627 }
3628
3629 if (!i || args[2][i]) {
3630 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3631 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3632 file, linenum, args[0], args[1]);
3633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
3635 }
3636 }
3637
3638 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3639 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3640 err_code |= ERR_ALERT | ERR_ABORT;
3641 goto out;
3642 }
3643 } else if (!strcmp(args[1], "show-desc")) {
3644 char *desc = NULL;
3645
3646 if (*args[2]) {
3647 int i, len=0;
3648 char *d;
3649
Willy Tarreau348acfe2014-04-14 15:00:39 +02003650 for (i = 2; *args[i]; i++)
3651 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003652
3653 desc = d = (char *)calloc(1, len);
3654
Willy Tarreau348acfe2014-04-14 15:00:39 +02003655 d += snprintf(d, desc + len - d, "%s", args[2]);
3656 for (i = 3; *args[i]; i++)
3657 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003658 }
3659
3660 if (!*args[2] && !global.desc)
3661 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3662 file, linenum, args[1]);
3663 else {
3664 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3665 free(desc);
3666 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3667 err_code |= ERR_ALERT | ERR_ABORT;
3668 goto out;
3669 }
3670 free(desc);
3671 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003672 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003673stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003674 Alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003675 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003676 err_code |= ERR_ALERT | ERR_FATAL;
3677 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003678 }
3679 }
3680 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003681 int optnum;
3682
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003683 if (*(args[1]) == '\0') {
3684 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3685 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003686 err_code |= ERR_ALERT | ERR_FATAL;
3687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003688 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003689
3690 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3691 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003692 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3693 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3694 file, linenum, cfg_opts[optnum].name);
3695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
3697 }
Willy Tarreau93893792009-07-23 13:19:11 +02003698 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3699 err_code |= ERR_WARN;
3700 goto out;
3701 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003702
Willy Tarreau3842f002009-06-14 11:39:52 +02003703 curproxy->no_options &= ~cfg_opts[optnum].val;
3704 curproxy->options &= ~cfg_opts[optnum].val;
3705
3706 switch (kwm) {
3707 case KWM_STD:
3708 curproxy->options |= cfg_opts[optnum].val;
3709 break;
3710 case KWM_NO:
3711 curproxy->no_options |= cfg_opts[optnum].val;
3712 break;
3713 case KWM_DEF: /* already cleared */
3714 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003715 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003716
Willy Tarreau93893792009-07-23 13:19:11 +02003717 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003718 }
3719 }
3720
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003721 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3722 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003723 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3724 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3725 file, linenum, cfg_opts2[optnum].name);
3726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
3728 }
Willy Tarreau93893792009-07-23 13:19:11 +02003729 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3730 err_code |= ERR_WARN;
3731 goto out;
3732 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003733
Willy Tarreau3842f002009-06-14 11:39:52 +02003734 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3735 curproxy->options2 &= ~cfg_opts2[optnum].val;
3736
3737 switch (kwm) {
3738 case KWM_STD:
3739 curproxy->options2 |= cfg_opts2[optnum].val;
3740 break;
3741 case KWM_NO:
3742 curproxy->no_options2 |= cfg_opts2[optnum].val;
3743 break;
3744 case KWM_DEF: /* already cleared */
3745 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003746 }
Willy Tarreau93893792009-07-23 13:19:11 +02003747 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003748 }
3749 }
3750
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003751 /* HTTP options override each other. They can be cancelled using
3752 * "no option xxx" which only switches to default mode if the mode
3753 * was this one (useful for cancelling options set in defaults
3754 * sections).
3755 */
3756 if (strcmp(args[1], "httpclose") == 0) {
3757 if (kwm == KWM_STD) {
3758 curproxy->options &= ~PR_O_HTTP_MODE;
3759 curproxy->options |= PR_O_HTTP_PCL;
3760 goto out;
3761 }
3762 else if (kwm == KWM_NO) {
3763 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3764 curproxy->options &= ~PR_O_HTTP_MODE;
3765 goto out;
3766 }
3767 }
3768 else if (strcmp(args[1], "forceclose") == 0) {
3769 if (kwm == KWM_STD) {
3770 curproxy->options &= ~PR_O_HTTP_MODE;
3771 curproxy->options |= PR_O_HTTP_FCL;
3772 goto out;
3773 }
3774 else if (kwm == KWM_NO) {
3775 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3776 curproxy->options &= ~PR_O_HTTP_MODE;
3777 goto out;
3778 }
3779 }
3780 else if (strcmp(args[1], "http-server-close") == 0) {
3781 if (kwm == KWM_STD) {
3782 curproxy->options &= ~PR_O_HTTP_MODE;
3783 curproxy->options |= PR_O_HTTP_SCL;
3784 goto out;
3785 }
3786 else if (kwm == KWM_NO) {
3787 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3788 curproxy->options &= ~PR_O_HTTP_MODE;
3789 goto out;
3790 }
3791 }
3792 else if (strcmp(args[1], "http-keep-alive") == 0) {
3793 if (kwm == KWM_STD) {
3794 curproxy->options &= ~PR_O_HTTP_MODE;
3795 curproxy->options |= PR_O_HTTP_KAL;
3796 goto out;
3797 }
3798 else if (kwm == KWM_NO) {
3799 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3800 curproxy->options &= ~PR_O_HTTP_MODE;
3801 goto out;
3802 }
3803 }
3804 else if (strcmp(args[1], "http-tunnel") == 0) {
3805 if (kwm == KWM_STD) {
3806 curproxy->options &= ~PR_O_HTTP_MODE;
3807 curproxy->options |= PR_O_HTTP_TUN;
3808 goto out;
3809 }
3810 else if (kwm == KWM_NO) {
3811 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3812 curproxy->options &= ~PR_O_HTTP_MODE;
3813 goto out;
3814 }
3815 }
3816
Willy Tarreau3842f002009-06-14 11:39:52 +02003817 if (kwm != KWM_STD) {
3818 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003819 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003820 err_code |= ERR_ALERT | ERR_FATAL;
3821 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003822 }
3823
Emeric Brun3a058f32009-06-30 18:26:00 +02003824 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003825 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003826 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003827 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003828 if (*(args[2]) != '\0') {
3829 if (!strcmp(args[2], "clf")) {
3830 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003831 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003832 } else {
3833 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003836 }
3837 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003838 if (curproxy->conf.logformat_string != default_http_log_format &&
3839 curproxy->conf.logformat_string != default_tcp_log_format &&
3840 curproxy->conf.logformat_string != clf_http_log_format)
3841 free(curproxy->conf.logformat_string);
3842 curproxy->conf.logformat_string = logformat;
3843
3844 free(curproxy->conf.lfs_file);
3845 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3846 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003847 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003848 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003849 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003850 if (curproxy->conf.logformat_string != default_http_log_format &&
3851 curproxy->conf.logformat_string != default_tcp_log_format &&
3852 curproxy->conf.logformat_string != clf_http_log_format)
3853 free(curproxy->conf.logformat_string);
3854 curproxy->conf.logformat_string = default_tcp_log_format;
3855
3856 free(curproxy->conf.lfs_file);
3857 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3858 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003859 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003860 else if (!strcmp(args[1], "tcpka")) {
3861 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003862 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003863 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003864
3865 if (curproxy->cap & PR_CAP_FE)
3866 curproxy->options |= PR_O_TCP_CLI_KA;
3867 if (curproxy->cap & PR_CAP_BE)
3868 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003869 }
3870 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003871 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003872 err_code |= ERR_WARN;
3873
Willy Tarreaubaaee002006-06-26 02:48:02 +02003874 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003875 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003876 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003877 curproxy->options2 &= ~PR_O2_CHK_ANY;
3878 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003879 if (!*args[2]) { /* no argument */
3880 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3881 curproxy->check_len = strlen(DEF_CHECK_REQ);
3882 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003883 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003884 curproxy->check_req = (char *)malloc(reqlen);
3885 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003886 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003887 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003888 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003889 if (*args[4])
3890 reqlen += strlen(args[4]);
3891 else
3892 reqlen += strlen("HTTP/1.0");
3893
3894 curproxy->check_req = (char *)malloc(reqlen);
3895 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003896 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003897 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003898 }
3899 else if (!strcmp(args[1], "ssl-hello-chk")) {
3900 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003901 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003902 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003903
Willy Tarreaua534fea2008-08-03 12:19:50 +02003904 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003905 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003906 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003907 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003908 }
Willy Tarreau23677902007-05-08 23:50:35 +02003909 else if (!strcmp(args[1], "smtpchk")) {
3910 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003911 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003912 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003913 curproxy->options2 &= ~PR_O2_CHK_ANY;
3914 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003915
3916 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3917 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3918 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3919 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3920 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3921 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3922 curproxy->check_req = (char *)malloc(reqlen);
3923 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3924 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3925 } else {
3926 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3927 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3928 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3929 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3930 }
3931 }
3932 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003933 else if (!strcmp(args[1], "pgsql-check")) {
3934 /* use PostgreSQL request to check servers' health */
3935 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3936 err_code |= ERR_WARN;
3937
3938 free(curproxy->check_req);
3939 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003940 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003941 curproxy->options2 |= PR_O2_PGSQL_CHK;
3942
3943 if (*(args[2])) {
3944 int cur_arg = 2;
3945
3946 while (*(args[cur_arg])) {
3947 if (strcmp(args[cur_arg], "user") == 0) {
3948 char * packet;
3949 uint32_t packet_len;
3950 uint32_t pv;
3951
3952 /* suboption header - needs additional argument for it */
3953 if (*(args[cur_arg+1]) == 0) {
3954 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3955 file, linenum, args[0], args[1], args[cur_arg]);
3956 err_code |= ERR_ALERT | ERR_FATAL;
3957 goto out;
3958 }
3959
3960 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3961 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3962 pv = htonl(0x30000); /* protocol version 3.0 */
3963
3964 packet = (char*) calloc(1, packet_len);
3965
3966 memcpy(packet + 4, &pv, 4);
3967
3968 /* copy "user" */
3969 memcpy(packet + 8, "user", 4);
3970
3971 /* copy username */
3972 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3973
3974 free(curproxy->check_req);
3975 curproxy->check_req = packet;
3976 curproxy->check_len = packet_len;
3977
3978 packet_len = htonl(packet_len);
3979 memcpy(packet, &packet_len, 4);
3980 cur_arg += 2;
3981 } else {
3982 /* unknown suboption - catchall */
3983 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3984 file, linenum, args[0], args[1]);
3985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
3987 }
3988 } /* end while loop */
3989 }
3990 }
3991
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003992 else if (!strcmp(args[1], "redis-check")) {
3993 /* use REDIS PING request to check servers' health */
3994 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3995 err_code |= ERR_WARN;
3996
3997 free(curproxy->check_req);
3998 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003999 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004000 curproxy->options2 |= PR_O2_REDIS_CHK;
4001
4002 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4003 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4004 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4005 }
4006
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004007 else if (!strcmp(args[1], "mysql-check")) {
4008 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004009 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4010 err_code |= ERR_WARN;
4011
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004012 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004013 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004014 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004015 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004016
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004017 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004018 * const char mysql40_client_auth_pkt[] = {
4019 * "\x0e\x00\x00" // packet length
4020 * "\x01" // packet number
4021 * "\x00\x00" // client capabilities
4022 * "\x00\x00\x01" // max packet
4023 * "haproxy\x00" // username (null terminated string)
4024 * "\x00" // filler (always 0x00)
4025 * "\x01\x00\x00" // packet length
4026 * "\x00" // packet number
4027 * "\x01" // COM_QUIT command
4028 * };
4029 */
4030
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004031 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4032 * const char mysql41_client_auth_pkt[] = {
4033 * "\x0e\x00\x00\" // packet length
4034 * "\x01" // packet number
4035 * "\x00\x00\x00\x00" // client capabilities
4036 * "\x00\x00\x00\x01" // max packet
4037 * "\x21" // character set (UTF-8)
4038 * char[23] // All zeroes
4039 * "haproxy\x00" // username (null terminated string)
4040 * "\x00" // filler (always 0x00)
4041 * "\x01\x00\x00" // packet length
4042 * "\x00" // packet number
4043 * "\x01" // COM_QUIT command
4044 * };
4045 */
4046
4047
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004048 if (*(args[2])) {
4049 int cur_arg = 2;
4050
4051 while (*(args[cur_arg])) {
4052 if (strcmp(args[cur_arg], "user") == 0) {
4053 char *mysqluser;
4054 int packetlen, reqlen, userlen;
4055
4056 /* suboption header - needs additional argument for it */
4057 if (*(args[cur_arg+1]) == 0) {
4058 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4059 file, linenum, args[0], args[1], args[cur_arg]);
4060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
4062 }
4063 mysqluser = args[cur_arg + 1];
4064 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004065
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004066 if (*(args[cur_arg+2])) {
4067 if (!strcmp(args[cur_arg+2], "post-41")) {
4068 packetlen = userlen + 7 + 27;
4069 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004070
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004071 free(curproxy->check_req);
4072 curproxy->check_req = (char *)calloc(1, reqlen);
4073 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004074
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004075 snprintf(curproxy->check_req, 4, "%c%c%c",
4076 ((unsigned char) packetlen & 0xff),
4077 ((unsigned char) (packetlen >> 8) & 0xff),
4078 ((unsigned char) (packetlen >> 16) & 0xff));
4079
4080 curproxy->check_req[3] = 1;
4081 curproxy->check_req[5] = 130;
4082 curproxy->check_req[11] = 1;
4083 curproxy->check_req[12] = 33;
4084 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4085 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4086 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4087 cur_arg += 3;
4088 } else {
4089 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
4092 }
4093 } else {
4094 packetlen = userlen + 7;
4095 reqlen = packetlen + 9;
4096
4097 free(curproxy->check_req);
4098 curproxy->check_req = (char *)calloc(1, reqlen);
4099 curproxy->check_len = reqlen;
4100
4101 snprintf(curproxy->check_req, 4, "%c%c%c",
4102 ((unsigned char) packetlen & 0xff),
4103 ((unsigned char) (packetlen >> 8) & 0xff),
4104 ((unsigned char) (packetlen >> 16) & 0xff));
4105
4106 curproxy->check_req[3] = 1;
4107 curproxy->check_req[5] = 128;
4108 curproxy->check_req[8] = 1;
4109 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4110 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4111 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4112 cur_arg += 2;
4113 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004114 } else {
4115 /* unknown suboption - catchall */
4116 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4117 file, linenum, args[0], args[1]);
4118 err_code |= ERR_ALERT | ERR_FATAL;
4119 goto out;
4120 }
4121 } /* end while loop */
4122 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004123 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004124 else if (!strcmp(args[1], "ldap-check")) {
4125 /* use LDAP request to check servers' health */
4126 free(curproxy->check_req);
4127 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004128 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004129 curproxy->options2 |= PR_O2_LDAP_CHK;
4130
4131 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4132 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4133 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4134 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004135 else if (!strcmp(args[1], "tcp-check")) {
4136 /* use raw TCPCHK send/expect to check servers' health */
4137 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4138 err_code |= ERR_WARN;
4139
4140 free(curproxy->check_req);
4141 curproxy->check_req = NULL;
4142 curproxy->options2 &= ~PR_O2_CHK_ANY;
4143 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4144 }
Simon Horman98637e52014-06-20 12:30:16 +09004145 else if (!strcmp(args[1], "external-check")) {
4146 /* excute an external command to check servers' health */
4147 free(curproxy->check_req);
4148 curproxy->check_req = NULL;
4149 curproxy->options2 &= ~PR_O2_CHK_ANY;
4150 curproxy->options2 |= PR_O2_EXT_CHK;
4151 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004152 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004153 int cur_arg;
4154
4155 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4156 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004157 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004158
Willy Tarreau87cf5142011-08-19 22:57:24 +02004159 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004160
4161 free(curproxy->fwdfor_hdr_name);
4162 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4163 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4164
4165 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4166 cur_arg = 2;
4167 while (*(args[cur_arg])) {
4168 if (!strcmp(args[cur_arg], "except")) {
4169 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004170 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004171 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4172 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004173 err_code |= ERR_ALERT | ERR_FATAL;
4174 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004175 }
4176 /* flush useless bits */
4177 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004178 cur_arg += 2;
4179 } else if (!strcmp(args[cur_arg], "header")) {
4180 /* suboption header - needs additional argument for it */
4181 if (*(args[cur_arg+1]) == 0) {
4182 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4183 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004186 }
4187 free(curproxy->fwdfor_hdr_name);
4188 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4189 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4190 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004191 } else if (!strcmp(args[cur_arg], "if-none")) {
4192 curproxy->options &= ~PR_O_FF_ALWAYS;
4193 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004194 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004195 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004196 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004197 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004198 err_code |= ERR_ALERT | ERR_FATAL;
4199 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004200 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004201 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004202 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004203 else if (!strcmp(args[1], "originalto")) {
4204 int cur_arg;
4205
4206 /* insert x-original-to field, but not for the IP address listed as an except.
4207 * set default options (ie: bitfield, header name, etc)
4208 */
4209
4210 curproxy->options |= PR_O_ORGTO;
4211
4212 free(curproxy->orgto_hdr_name);
4213 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4214 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4215
Willy Tarreau87cf5142011-08-19 22:57:24 +02004216 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004217 cur_arg = 2;
4218 while (*(args[cur_arg])) {
4219 if (!strcmp(args[cur_arg], "except")) {
4220 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004221 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_to, &curproxy->except_mask_to)) {
Maik Broemme2850cb42009-04-17 18:53:21 +02004222 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4223 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004224 err_code |= ERR_ALERT | ERR_FATAL;
4225 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004226 }
4227 /* flush useless bits */
4228 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4229 cur_arg += 2;
4230 } else if (!strcmp(args[cur_arg], "header")) {
4231 /* suboption header - needs additional argument for it */
4232 if (*(args[cur_arg+1]) == 0) {
4233 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4234 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004235 err_code |= ERR_ALERT | ERR_FATAL;
4236 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004237 }
4238 free(curproxy->orgto_hdr_name);
4239 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4240 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4241 cur_arg += 2;
4242 } else {
4243 /* unknown suboption - catchall */
4244 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4245 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004246 err_code |= ERR_ALERT | ERR_FATAL;
4247 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004248 }
4249 } /* end while loop */
4250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004251 else {
4252 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004253 err_code |= ERR_ALERT | ERR_FATAL;
4254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004255 }
Willy Tarreau93893792009-07-23 13:19:11 +02004256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004257 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004258 else if (!strcmp(args[0], "default_backend")) {
4259 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004260 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004261
4262 if (*(args[1]) == 0) {
4263 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004264 err_code |= ERR_ALERT | ERR_FATAL;
4265 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004266 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004267 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004268 curproxy->defbe.name = strdup(args[1]);
4269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004270 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004271 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004272 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004273
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004274 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4275 Warning("parsing [%s:%d]: keyword '%s' is deprecated in favor of 'option redispatch', and will not be supported by future versions.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004276 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004277 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004278 /* enable reconnections to dispatch */
4279 curproxy->options |= PR_O_REDISP;
4280 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004281 else if (!strcmp(args[0], "http-check")) {
4282 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004283 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004284
4285 if (strcmp(args[1], "disable-on-404") == 0) {
4286 /* enable a graceful server shutdown on an HTTP 404 response */
4287 curproxy->options |= PR_O_DISABLE404;
4288 }
Willy Tarreauef781042010-01-27 11:53:01 +01004289 else if (strcmp(args[1], "send-state") == 0) {
4290 /* enable emission of the apparent state of a server in HTTP checks */
4291 curproxy->options2 |= PR_O2_CHK_SNDST;
4292 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004293 else if (strcmp(args[1], "expect") == 0) {
4294 const char *ptr_arg;
4295 int cur_arg;
4296
4297 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4298 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
4301 }
4302
4303 cur_arg = 2;
4304 /* consider exclamation marks, sole or at the beginning of a word */
4305 while (*(ptr_arg = args[cur_arg])) {
4306 while (*ptr_arg == '!') {
4307 curproxy->options2 ^= PR_O2_EXP_INV;
4308 ptr_arg++;
4309 }
4310 if (*ptr_arg)
4311 break;
4312 cur_arg++;
4313 }
4314 /* now ptr_arg points to the beginning of a word past any possible
4315 * exclamation mark, and cur_arg is the argument which holds this word.
4316 */
4317 if (strcmp(ptr_arg, "status") == 0) {
4318 if (!*(args[cur_arg + 1])) {
4319 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4320 file, linenum, args[0], args[1], ptr_arg);
4321 err_code |= ERR_ALERT | ERR_FATAL;
4322 goto out;
4323 }
4324 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004325 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004326 curproxy->expect_str = strdup(args[cur_arg + 1]);
4327 }
4328 else if (strcmp(ptr_arg, "string") == 0) {
4329 if (!*(args[cur_arg + 1])) {
4330 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4331 file, linenum, args[0], args[1], ptr_arg);
4332 err_code |= ERR_ALERT | ERR_FATAL;
4333 goto out;
4334 }
4335 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004336 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004337 curproxy->expect_str = strdup(args[cur_arg + 1]);
4338 }
4339 else if (strcmp(ptr_arg, "rstatus") == 0) {
4340 if (!*(args[cur_arg + 1])) {
4341 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4342 file, linenum, args[0], args[1], ptr_arg);
4343 err_code |= ERR_ALERT | ERR_FATAL;
4344 goto out;
4345 }
4346 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004347 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004348 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004349 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004350 free(curproxy->expect_regex);
4351 curproxy->expect_regex = NULL;
4352 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004353 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004354 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4355 error = NULL;
4356 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4357 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4358 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4359 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004360 err_code |= ERR_ALERT | ERR_FATAL;
4361 goto out;
4362 }
4363 }
4364 else if (strcmp(ptr_arg, "rstring") == 0) {
4365 if (!*(args[cur_arg + 1])) {
4366 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4367 file, linenum, args[0], args[1], ptr_arg);
4368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
4370 }
4371 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004372 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004373 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004374 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004375 free(curproxy->expect_regex);
4376 curproxy->expect_regex = NULL;
4377 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004378 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004379 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4380 error = NULL;
4381 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4382 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4383 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4384 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004385 err_code |= ERR_ALERT | ERR_FATAL;
4386 goto out;
4387 }
4388 }
4389 else {
4390 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4391 file, linenum, args[0], args[1], ptr_arg);
4392 err_code |= ERR_ALERT | ERR_FATAL;
4393 goto out;
4394 }
4395 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004396 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004397 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'send-state', 'expect'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004398 err_code |= ERR_ALERT | ERR_FATAL;
4399 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004400 }
4401 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004402 else if (!strcmp(args[0], "tcp-check")) {
4403 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4404 err_code |= ERR_WARN;
4405
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004406 if (strcmp(args[1], "connect") == 0) {
4407 const char *ptr_arg;
4408 int cur_arg;
4409 struct tcpcheck_rule *tcpcheck;
4410 struct list *l;
4411
4412 /* check if first rule is also a 'connect' action */
4413 l = (struct list *)&curproxy->tcpcheck_rules;
4414 if (l->p != l->n) {
4415 tcpcheck = (struct tcpcheck_rule *)l->n;
4416 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4417 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4418 file, linenum);
4419 err_code |= ERR_ALERT | ERR_FATAL;
4420 goto out;
4421 }
4422 }
4423
4424 cur_arg = 2;
4425 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4426 tcpcheck->action = TCPCHK_ACT_CONNECT;
4427
4428 /* parsing each parameters to fill up the rule */
4429 while (*(ptr_arg = args[cur_arg])) {
4430 /* tcp port */
4431 if (strcmp(args[cur_arg], "port") == 0) {
4432 if ( (atol(args[cur_arg + 1]) > 65535) ||
4433 (atol(args[cur_arg + 1]) < 1) ){
4434 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4435 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4436 err_code |= ERR_ALERT | ERR_FATAL;
4437 goto out;
4438 }
4439 tcpcheck->port = atol(args[cur_arg + 1]);
4440 cur_arg += 2;
4441 }
4442 /* send proxy protocol */
4443 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4444 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4445 cur_arg++;
4446 }
4447#ifdef USE_OPENSSL
4448 else if (strcmp(args[cur_arg], "ssl") == 0) {
4449 curproxy->options |= PR_O_TCPCHK_SSL;
4450 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4451 cur_arg++;
4452 }
4453#endif /* USE_OPENSSL */
4454 else {
4455#ifdef USE_OPENSSL
4456 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4457#else /* USE_OPENSSL */
4458 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4459#endif /* USE_OPENSSL */
4460 file, linenum, args[0], args[1], args[cur_arg]);
4461 err_code |= ERR_ALERT | ERR_FATAL;
4462 goto out;
4463 }
4464
4465 }
4466
4467 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4468 }
4469 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004470 if (! *(args[2]) ) {
4471 /* SEND string expected */
4472 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4473 file, linenum, args[0], args[1], args[2]);
4474 err_code |= ERR_ALERT | ERR_FATAL;
4475 goto out;
4476 } else {
4477 struct tcpcheck_rule *tcpcheck;
4478
4479 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4480
4481 tcpcheck->action = TCPCHK_ACT_SEND;
4482 tcpcheck->string_len = strlen(args[2]);
4483 tcpcheck->string = strdup(args[2]);
4484 tcpcheck->expect_regex = NULL;
4485
4486 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4487 }
4488 }
4489 else if (strcmp(args[1], "send-binary") == 0) {
4490 if (! *(args[2]) ) {
4491 /* SEND binary string expected */
4492 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4493 file, linenum, args[0], args[1], args[2]);
4494 err_code |= ERR_ALERT | ERR_FATAL;
4495 goto out;
4496 } else {
4497 struct tcpcheck_rule *tcpcheck;
4498 char *err = NULL;
4499
4500 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4501
4502 tcpcheck->action = TCPCHK_ACT_SEND;
4503 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4504 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4505 file, linenum, args[0], args[1], args[2], err);
4506 err_code |= ERR_ALERT | ERR_FATAL;
4507 goto out;
4508 }
4509 tcpcheck->expect_regex = NULL;
4510
4511 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4512 }
4513 }
4514 else if (strcmp(args[1], "expect") == 0) {
4515 const char *ptr_arg;
4516 int cur_arg;
4517 int inverse = 0;
4518
4519 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4520 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4521 err_code |= ERR_ALERT | ERR_FATAL;
4522 goto out;
4523 }
4524
4525 cur_arg = 2;
4526 /* consider exclamation marks, sole or at the beginning of a word */
4527 while (*(ptr_arg = args[cur_arg])) {
4528 while (*ptr_arg == '!') {
4529 inverse = !inverse;
4530 ptr_arg++;
4531 }
4532 if (*ptr_arg)
4533 break;
4534 cur_arg++;
4535 }
4536 /* now ptr_arg points to the beginning of a word past any possible
4537 * exclamation mark, and cur_arg is the argument which holds this word.
4538 */
4539 if (strcmp(ptr_arg, "binary") == 0) {
4540 if (!*(args[cur_arg + 1])) {
4541 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4542 file, linenum, args[0], args[1], ptr_arg);
4543 err_code |= ERR_ALERT | ERR_FATAL;
4544 goto out;
4545 }
4546 struct tcpcheck_rule *tcpcheck;
4547 char *err = NULL;
4548
4549 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4550
4551 tcpcheck->action = TCPCHK_ACT_EXPECT;
4552 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4553 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4554 file, linenum, args[0], args[1], args[2], err);
4555 err_code |= ERR_ALERT | ERR_FATAL;
4556 goto out;
4557 }
4558 tcpcheck->expect_regex = NULL;
4559 tcpcheck->inverse = inverse;
4560
4561 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4562 }
4563 else if (strcmp(ptr_arg, "string") == 0) {
4564 if (!*(args[cur_arg + 1])) {
4565 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4566 file, linenum, args[0], args[1], ptr_arg);
4567 err_code |= ERR_ALERT | ERR_FATAL;
4568 goto out;
4569 }
4570 struct tcpcheck_rule *tcpcheck;
4571
4572 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4573
4574 tcpcheck->action = TCPCHK_ACT_EXPECT;
4575 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4576 tcpcheck->string = strdup(args[cur_arg + 1]);
4577 tcpcheck->expect_regex = NULL;
4578 tcpcheck->inverse = inverse;
4579
4580 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4581 }
4582 else if (strcmp(ptr_arg, "rstring") == 0) {
4583 if (!*(args[cur_arg + 1])) {
4584 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4585 file, linenum, args[0], args[1], ptr_arg);
4586 err_code |= ERR_ALERT | ERR_FATAL;
4587 goto out;
4588 }
4589 struct tcpcheck_rule *tcpcheck;
4590
4591 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4592
4593 tcpcheck->action = TCPCHK_ACT_EXPECT;
4594 tcpcheck->string_len = 0;
4595 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004596 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4597 error = NULL;
4598 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4599 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4600 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4601 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004602 err_code |= ERR_ALERT | ERR_FATAL;
4603 goto out;
4604 }
4605 tcpcheck->inverse = inverse;
4606
4607 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4608 }
4609 else {
4610 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4611 file, linenum, args[0], args[1], ptr_arg);
4612 err_code |= ERR_ALERT | ERR_FATAL;
4613 goto out;
4614 }
4615 }
4616 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004617 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004618 err_code |= ERR_ALERT | ERR_FATAL;
4619 goto out;
4620 }
4621 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004622 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004623 if (curproxy == &defproxy) {
4624 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004625 err_code |= ERR_ALERT | ERR_FATAL;
4626 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004627 }
4628
Willy Tarreaub80c2302007-11-30 20:51:32 +01004629 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004630 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004631
4632 if (strcmp(args[1], "fail") == 0) {
4633 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004634 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004635 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4636 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004639 }
4640
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004641 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4642 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4643 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004644 err_code |= ERR_ALERT | ERR_FATAL;
4645 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004646 }
4647 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4648 }
4649 else {
4650 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004651 err_code |= ERR_ALERT | ERR_FATAL;
4652 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004653 }
4654 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004655#ifdef TPROXY
4656 else if (!strcmp(args[0], "transparent")) {
4657 /* enable transparent proxy connections */
4658 curproxy->options |= PR_O_TRANSP;
4659 }
4660#endif
4661 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004662 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004663 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004664
Willy Tarreaubaaee002006-06-26 02:48:02 +02004665 if (*(args[1]) == 0) {
4666 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004669 }
4670 curproxy->maxconn = atol(args[1]);
4671 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004672 else if (!strcmp(args[0], "backlog")) { /* backlog */
4673 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004674 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004675
4676 if (*(args[1]) == 0) {
4677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004678 err_code |= ERR_ALERT | ERR_FATAL;
4679 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004680 }
4681 curproxy->backlog = atol(args[1]);
4682 }
Willy Tarreau86034312006-12-29 00:10:33 +01004683 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004684 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004685 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004686
Willy Tarreau86034312006-12-29 00:10:33 +01004687 if (*(args[1]) == 0) {
4688 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004689 err_code |= ERR_ALERT | ERR_FATAL;
4690 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004691 }
4692 curproxy->fullconn = atol(args[1]);
4693 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004694 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4695 if (*(args[1]) == 0) {
4696 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004697 err_code |= ERR_ALERT | ERR_FATAL;
4698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004699 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004700 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4701 if (err) {
4702 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4703 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004704 err_code |= ERR_ALERT | ERR_FATAL;
4705 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004706 }
4707 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004708 }
4709 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004710 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004711 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004712 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004713
Willy Tarreaubaaee002006-06-26 02:48:02 +02004714 if (curproxy == &defproxy) {
4715 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004716 err_code |= ERR_ALERT | ERR_FATAL;
4717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004718 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004719 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004720 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004721
Willy Tarreau902636f2013-03-10 19:44:48 +01004722 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004723 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004724 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004725 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004726 goto out;
4727 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004728
4729 proto = protocol_by_family(sk->ss_family);
4730 if (!proto || !proto->connect) {
4731 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4732 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004733 err_code |= ERR_ALERT | ERR_FATAL;
4734 goto out;
4735 }
4736
4737 if (port1 != port2) {
4738 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4739 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004740 err_code |= ERR_ALERT | ERR_FATAL;
4741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004742 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004743
4744 if (!port1) {
4745 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4746 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004747 err_code |= ERR_ALERT | ERR_FATAL;
4748 goto out;
4749 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004750
Willy Tarreaud5191e72010-02-09 20:50:45 +01004751 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004752 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004753 }
4754 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004755 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004756 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004757
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004758 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4759 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004760 err_code |= ERR_ALERT | ERR_FATAL;
4761 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004762 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004764 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004765 /**
4766 * The syntax for hash-type config element is
4767 * hash-type {map-based|consistent} [[<algo>] avalanche]
4768 *
4769 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4770 */
4771 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004772
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004773 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4774 err_code |= ERR_WARN;
4775
4776 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004777 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4778 }
4779 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004780 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4781 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004782 else if (strcmp(args[1], "avalanche") == 0) {
4783 Alert("parsing [%s:%d] : experimental feature '%s %s' is not supported anymore, please use '%s map-based sdbm avalanche' instead.\n", file, linenum, args[0], args[1], args[0]);
4784 err_code |= ERR_ALERT | ERR_FATAL;
4785 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004786 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004787 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004788 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004789 err_code |= ERR_ALERT | ERR_FATAL;
4790 goto out;
4791 }
Bhaskar98634f02013-10-29 23:30:51 -04004792
4793 /* set the hash function to use */
4794 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004795 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004796 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004797
4798 /* if consistent with no argument, then avalanche modifier is also applied */
4799 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4800 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004801 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004802 /* set the hash function */
4803 if (!strcmp(args[2], "sdbm")) {
4804 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4805 }
4806 else if (!strcmp(args[2], "djb2")) {
4807 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004808 } else if (!strcmp(args[2], "wt6")) {
4809 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004810 }
4811 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004812 Alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2' or 'wt6' hash functions.\n", file, linenum, args[0]);
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004813 err_code |= ERR_ALERT | ERR_FATAL;
4814 goto out;
4815 }
4816
4817 /* set the hash modifier */
4818 if (!strcmp(args[3], "avalanche")) {
4819 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4820 }
4821 else if (*args[3]) {
4822 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4823 err_code |= ERR_ALERT | ERR_FATAL;
4824 goto out;
4825 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004826 }
William Lallemanda73203e2012-03-12 12:48:57 +01004827 }
William Lallemanda73203e2012-03-12 12:48:57 +01004828 else if (strcmp(args[0], "unique-id-format") == 0) {
4829 if (!*(args[1])) {
4830 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4831 err_code |= ERR_ALERT | ERR_FATAL;
4832 goto out;
4833 }
William Lallemand3203ff42012-11-11 17:30:56 +01004834 if (*(args[2])) {
4835 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4836 err_code |= ERR_ALERT | ERR_FATAL;
4837 goto out;
4838 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004839 free(curproxy->conf.uniqueid_format_string);
4840 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004841
Willy Tarreau62a61232013-04-12 18:13:46 +02004842 free(curproxy->conf.uif_file);
4843 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4844 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004845 }
William Lallemanda73203e2012-03-12 12:48:57 +01004846
4847 else if (strcmp(args[0], "unique-id-header") == 0) {
4848 if (!*(args[1])) {
4849 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4850 err_code |= ERR_ALERT | ERR_FATAL;
4851 goto out;
4852 }
4853 free(curproxy->header_unique_id);
4854 curproxy->header_unique_id = strdup(args[1]);
4855 }
4856
William Lallemand723b73a2012-02-08 16:37:49 +01004857 else if (strcmp(args[0], "log-format") == 0) {
4858 if (!*(args[1])) {
4859 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
4862 }
William Lallemand3203ff42012-11-11 17:30:56 +01004863 if (*(args[2])) {
4864 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4865 err_code |= ERR_ALERT | ERR_FATAL;
4866 goto out;
4867 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004868
Willy Tarreau62a61232013-04-12 18:13:46 +02004869 if (curproxy->conf.logformat_string != default_http_log_format &&
4870 curproxy->conf.logformat_string != default_tcp_log_format &&
4871 curproxy->conf.logformat_string != clf_http_log_format)
4872 free(curproxy->conf.logformat_string);
4873 curproxy->conf.logformat_string = strdup(args[1]);
4874
4875 free(curproxy->conf.lfs_file);
4876 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4877 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004878
4879 /* get a chance to improve log-format error reporting by
4880 * reporting the correct line-number when possible.
4881 */
4882 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4883 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4884 file, linenum, curproxy->id);
4885 err_code |= ERR_WARN;
4886 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004887 }
William Lallemand723b73a2012-02-08 16:37:49 +01004888
William Lallemand0f99e342011-10-12 17:50:54 +02004889 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4890 /* delete previous herited or defined syslog servers */
4891 struct logsrv *back;
4892
4893 if (*(args[1]) != 0) {
4894 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4895 err_code |= ERR_ALERT | ERR_FATAL;
4896 goto out;
4897 }
4898
William Lallemand723b73a2012-02-08 16:37:49 +01004899 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4900 LIST_DEL(&tmplogsrv->list);
4901 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004902 }
4903 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004904 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004905 struct logsrv *logsrv;
4906
Willy Tarreaubaaee002006-06-26 02:48:02 +02004907 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004908 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004909 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004910 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004911 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004912 LIST_INIT(&node->list);
4913 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4914 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004915 }
4916 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004917 struct sockaddr_storage *sk;
4918 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02004919 int arg = 0;
4920 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004921
4922 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004923
Willy Tarreau18324f52014-06-27 18:10:07 +02004924 /* just after the address, a length may be specified */
4925 if (strcmp(args[arg+2], "len") == 0) {
4926 len = atoi(args[arg+3]);
4927 if (len < 80 || len > 65535) {
4928 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4929 file, linenum, args[arg+3]);
4930 err_code |= ERR_ALERT | ERR_FATAL;
4931 goto out;
4932 }
4933 logsrv->maxlen = len;
4934
4935 /* skip these two args */
4936 arg += 2;
4937 }
4938 else
4939 logsrv->maxlen = MAX_SYSLOG_LEN;
4940
4941 if (logsrv->maxlen > global.max_syslog_len) {
4942 global.max_syslog_len = logsrv->maxlen;
4943 logline = realloc(logline, global.max_syslog_len + 1);
4944 }
4945
4946 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004947 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004948 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004949 err_code |= ERR_ALERT | ERR_FATAL;
4950 goto out;
4951
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 }
4953
William Lallemand0f99e342011-10-12 17:50:54 +02004954 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02004955 if (*(args[arg+3])) {
4956 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004957 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004958 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004959 err_code |= ERR_ALERT | ERR_FATAL;
4960 goto out;
4961
Willy Tarreaubaaee002006-06-26 02:48:02 +02004962 }
4963 }
4964
William Lallemand0f99e342011-10-12 17:50:54 +02004965 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02004966 if (*(args[arg+4])) {
4967 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004968 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004969 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004970 err_code |= ERR_ALERT | ERR_FATAL;
4971 goto out;
4972
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004973 }
4974 }
4975
Willy Tarreau902636f2013-03-10 19:44:48 +01004976 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004977 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004978 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004979 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004980 goto out;
4981 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004982
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004983 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004984
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004985 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004986 if (port1 != port2) {
4987 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4988 file, linenum, args[0], args[1]);
4989 err_code |= ERR_ALERT | ERR_FATAL;
4990 goto out;
4991 }
4992
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004993 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004994 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004995 }
William Lallemand0f99e342011-10-12 17:50:54 +02004996
4997 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004998 }
4999 else {
5000 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5001 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005002 err_code |= ERR_ALERT | ERR_FATAL;
5003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005004 }
5005 }
5006 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005007 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005008 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005009 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005010 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005011
Willy Tarreau977b8e42006-12-29 14:19:17 +01005012 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005013 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005014
Willy Tarreaubaaee002006-06-26 02:48:02 +02005015 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005016 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5017 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005018 err_code |= ERR_ALERT | ERR_FATAL;
5019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005021
5022 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005023 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5024 free(curproxy->conn_src.iface_name);
5025 curproxy->conn_src.iface_name = NULL;
5026 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005027
Willy Tarreau902636f2013-03-10 19:44:48 +01005028 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005029 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005030 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005031 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005032 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005033 goto out;
5034 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005035
5036 proto = protocol_by_family(sk->ss_family);
5037 if (!proto || !proto->connect) {
5038 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005039 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005040 err_code |= ERR_ALERT | ERR_FATAL;
5041 goto out;
5042 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005043
5044 if (port1 != port2) {
5045 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5046 file, linenum, args[0], args[1]);
5047 err_code |= ERR_ALERT | ERR_FATAL;
5048 goto out;
5049 }
5050
Willy Tarreauef9a3602012-12-08 22:29:20 +01005051 curproxy->conn_src.source_addr = *sk;
5052 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005053
5054 cur_arg = 2;
5055 while (*(args[cur_arg])) {
5056 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005057#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5058#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005059 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005060 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5061 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005062 err_code |= ERR_ALERT | ERR_FATAL;
5063 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005064 }
5065#endif
5066 if (!*args[cur_arg + 1]) {
5067 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5068 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005069 err_code |= ERR_ALERT | ERR_FATAL;
5070 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005071 }
5072
5073 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005074 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5075 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005076 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005077 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5078 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005079 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5080 char *name, *end;
5081
5082 name = args[cur_arg+1] + 7;
5083 while (isspace(*name))
5084 name++;
5085
5086 end = name;
5087 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5088 end++;
5089
Willy Tarreauef9a3602012-12-08 22:29:20 +01005090 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5091 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5092 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5093 curproxy->conn_src.bind_hdr_len = end - name;
5094 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5095 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5096 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005097
5098 /* now look for an occurrence number */
5099 while (isspace(*end))
5100 end++;
5101 if (*end == ',') {
5102 end++;
5103 name = end;
5104 if (*end == '-')
5105 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005106 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005107 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005108 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005109 }
5110
Willy Tarreauef9a3602012-12-08 22:29:20 +01005111 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005112 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5113 " occurrences values smaller than %d.\n",
5114 file, linenum, MAX_HDR_HISTORY);
5115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
5117 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005118 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005119 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005120
Willy Tarreau902636f2013-03-10 19:44:48 +01005121 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005122 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005123 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005124 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005125 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005126 goto out;
5127 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005128
5129 proto = protocol_by_family(sk->ss_family);
5130 if (!proto || !proto->connect) {
5131 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5132 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005133 err_code |= ERR_ALERT | ERR_FATAL;
5134 goto out;
5135 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005136
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005137 if (port1 != port2) {
5138 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5139 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005140 err_code |= ERR_ALERT | ERR_FATAL;
5141 goto out;
5142 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005143 curproxy->conn_src.tproxy_addr = *sk;
5144 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005145 }
5146 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005147#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005148 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005149#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005150#else /* no TPROXY support */
5151 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005152 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005153 err_code |= ERR_ALERT | ERR_FATAL;
5154 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005155#endif
5156 cur_arg += 2;
5157 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005158 }
5159
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005160 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5161#ifdef SO_BINDTODEVICE
5162 if (!*args[cur_arg + 1]) {
5163 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5164 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005165 err_code |= ERR_ALERT | ERR_FATAL;
5166 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005167 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005168 free(curproxy->conn_src.iface_name);
5169 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5170 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005171 global.last_checks |= LSTCHK_NETADM;
5172#else
5173 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5174 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005175 err_code |= ERR_ALERT | ERR_FATAL;
5176 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005177#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005178 cur_arg += 2;
5179 continue;
5180 }
5181 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005182 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005185 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005186 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005187 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5188 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5189 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005190 err_code |= ERR_ALERT | ERR_FATAL;
5191 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005192 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005193 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005194 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005195 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5196 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005197 err_code |= ERR_ALERT | ERR_FATAL;
5198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005200
5201 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005202 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005203 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005204 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005206 }
5207 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005208 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005209 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005210 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005211 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005213 }
5214 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005215 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005216 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005217 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005218 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005219 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005220 }
5221 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005222 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005223 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005224 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005225 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005227 }
5228 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005229 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005230 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005231 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005232 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005234 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005235 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005236 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005237 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005238 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005239 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005240 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005241 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005242 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005243 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005244 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005245 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005246 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005247 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005248
5249 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5250 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of the more efficient 'use_backend' which uses a different but more powerful syntax. Future versions will not support '%s' anymore, you should convert it now!\n", file, linenum, args[0], args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01005251 }
5252 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005253 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005254 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005255 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005256 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005257 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005258
5259 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5260 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of the more efficient 'use_backend' which uses a different but more powerful syntax. Future versions will not support '%s' anymore, you should convert it now!\n", file, linenum, args[0], args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01005261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005262 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005263 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005264 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5265 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005266 err_code |= ERR_ALERT | ERR_FATAL;
5267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005268 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005269
5270 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005271 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005272 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005273 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005274 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005275 }
5276 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005277 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005278 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005279 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005280 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005282 }
5283 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005284 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005285 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005286 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005287 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005289 }
5290 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005291 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005292 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005293 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005294 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296 }
5297 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005298 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005299 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005300 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005301 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005303 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005304 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005305 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005306 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005307 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005308 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005309 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005310 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005311 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005312 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005313
Willy Tarreaubaaee002006-06-26 02:48:02 +02005314 if (curproxy == &defproxy) {
5315 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005316 err_code |= ERR_ALERT | ERR_FATAL;
5317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005318 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005319 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005320 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321
Willy Tarreaubaaee002006-06-26 02:48:02 +02005322 if (*(args[1]) == 0) {
5323 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005324 err_code |= ERR_ALERT | ERR_FATAL;
5325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005327
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005328 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005329 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5330 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5331 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005332 err_code |= ERR_ALERT | ERR_FATAL;
5333 goto out;
5334 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005335 err_code |= warnif_cond_conflicts(cond,
5336 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5337 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005338 }
5339 else if (*args[2]) {
5340 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5341 file, linenum, args[0], args[2]);
5342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
5344 }
5345
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005346 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005347 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005348 wl->s = strdup(args[1]);
5349 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005350 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005351 }
5352 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005353 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005354 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5355 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005356 err_code |= ERR_ALERT | ERR_FATAL;
5357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005358 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005359
Willy Tarreauade5ec42010-01-28 19:33:49 +01005360 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005361 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005362 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005363 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005365 }
5366 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005367 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005368 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005369 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005370 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005372 }
5373 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005374 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005375 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005376 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005377 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005379 }
5380 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005381 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005382 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5383 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005384 err_code |= ERR_ALERT | ERR_FATAL;
5385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005386 }
5387
Willy Tarreauade5ec42010-01-28 19:33:49 +01005388 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005389 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005390 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005391 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005393 }
5394 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005395 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005396 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005397 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005398 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005400 }
5401 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005402 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005403 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005404 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005405 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005407 }
5408 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005409 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005410
Willy Tarreaubaaee002006-06-26 02:48:02 +02005411 if (curproxy == &defproxy) {
5412 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005413 err_code |= ERR_ALERT | ERR_FATAL;
5414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005415 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005416 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005417 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005418
Willy Tarreaubaaee002006-06-26 02:48:02 +02005419 if (*(args[1]) == 0) {
5420 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005421 err_code |= ERR_ALERT | ERR_FATAL;
5422 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005423 }
5424
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005425 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005426 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5427 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5428 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005429 err_code |= ERR_ALERT | ERR_FATAL;
5430 goto out;
5431 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005432 err_code |= warnif_cond_conflicts(cond,
5433 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5434 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005435 }
5436 else if (*args[2]) {
5437 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5438 file, linenum, args[0], args[2]);
5439 err_code |= ERR_ALERT | ERR_FATAL;
5440 goto out;
5441 }
5442
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005443 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005444 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005445 wl->s = strdup(args[1]);
5446 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005447 }
5448 else if (!strcmp(args[0], "errorloc") ||
5449 !strcmp(args[0], "errorloc302") ||
5450 !strcmp(args[0], "errorloc303")) { /* error location */
5451 int errnum, errlen;
5452 char *err;
5453
Willy Tarreau977b8e42006-12-29 14:19:17 +01005454 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005455 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005456
Willy Tarreaubaaee002006-06-26 02:48:02 +02005457 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005458 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005459 err_code |= ERR_ALERT | ERR_FATAL;
5460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005461 }
5462
5463 errnum = atol(args[1]);
5464 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005465 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5466 err = malloc(errlen);
5467 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005469 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5470 err = malloc(errlen);
5471 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005472 }
5473
Willy Tarreau0f772532006-12-23 20:51:41 +01005474 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5475 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005476 chunk_destroy(&curproxy->errmsg[rc]);
5477 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005478 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005480 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005481
5482 if (rc >= HTTP_ERR_SIZE) {
5483 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5484 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005485 free(err);
5486 }
5487 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005488 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5489 int errnum, errlen, fd;
5490 char *err;
5491 struct stat stat;
5492
5493 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005494 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005495
5496 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005497 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005498 err_code |= ERR_ALERT | ERR_FATAL;
5499 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005500 }
5501
5502 fd = open(args[2], O_RDONLY);
5503 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5504 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5505 file, linenum, args[2], args[1]);
5506 if (fd >= 0)
5507 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005508 err_code |= ERR_ALERT | ERR_FATAL;
5509 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005510 }
5511
Willy Tarreau27a674e2009-08-17 07:23:33 +02005512 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005513 errlen = stat.st_size;
5514 } else {
5515 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005516 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005517 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005518 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005519 }
5520
5521 err = malloc(errlen); /* malloc() must succeed during parsing */
5522 errnum = read(fd, err, errlen);
5523 if (errnum != errlen) {
5524 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5525 file, linenum, args[2], args[1]);
5526 close(fd);
5527 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005528 err_code |= ERR_ALERT | ERR_FATAL;
5529 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005530 }
5531 close(fd);
5532
5533 errnum = atol(args[1]);
5534 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5535 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005536 chunk_destroy(&curproxy->errmsg[rc]);
5537 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005538 break;
5539 }
5540 }
5541
5542 if (rc >= HTTP_ERR_SIZE) {
5543 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5544 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005545 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005546 free(err);
5547 }
5548 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005549 else if (!strcmp(args[0], "compression")) {
5550 struct comp *comp;
5551 if (curproxy->comp == NULL) {
5552 comp = calloc(1, sizeof(struct comp));
5553 curproxy->comp = comp;
5554 } else {
5555 comp = curproxy->comp;
5556 }
5557
5558 if (!strcmp(args[1], "algo")) {
5559 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005560 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005561
William Lallemand82fe75c2012-10-23 10:25:10 +02005562 cur_arg = 2;
5563 if (!*args[cur_arg]) {
5564 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5565 file, linenum, args[0]);
5566 err_code |= ERR_ALERT | ERR_FATAL;
5567 goto out;
5568 }
5569 while (*(args[cur_arg])) {
5570 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5571 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5572 file, linenum, args[0], args[cur_arg]);
5573 err_code |= ERR_ALERT | ERR_FATAL;
5574 goto out;
5575 }
William Lallemand552df672012-11-07 13:21:47 +01005576 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5577 curproxy->comp->algos->end(&ctx);
5578 } else {
5579 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5580 file, linenum, args[0], args[cur_arg]);
5581 err_code |= ERR_ALERT | ERR_FATAL;
5582 goto out;
5583 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005584 cur_arg ++;
5585 continue;
5586 }
5587 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005588 else if (!strcmp(args[1], "offload")) {
5589 comp->offload = 1;
5590 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005591 else if (!strcmp(args[1], "type")) {
5592 int cur_arg;
5593 cur_arg = 2;
5594 if (!*args[cur_arg]) {
5595 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5596 file, linenum, args[0]);
5597 err_code |= ERR_ALERT | ERR_FATAL;
5598 goto out;
5599 }
5600 while (*(args[cur_arg])) {
5601 comp_append_type(comp, args[cur_arg]);
5602 cur_arg ++;
5603 continue;
5604 }
5605 }
5606 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005607 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005608 file, linenum, args[0]);
5609 err_code |= ERR_ALERT | ERR_FATAL;
5610 goto out;
5611 }
5612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005613 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005614 struct cfg_kw_list *kwl;
5615 int index;
5616
5617 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5618 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5619 if (kwl->kw[index].section != CFG_LISTEN)
5620 continue;
5621 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5622 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005623 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005624 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005625 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005626 err_code |= ERR_ALERT | ERR_FATAL;
5627 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005628 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005629 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005630 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005631 err_code |= ERR_WARN;
5632 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005633 }
Willy Tarreau93893792009-07-23 13:19:11 +02005634 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005635 }
5636 }
5637 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005638
Willy Tarreau6daf3432008-01-22 16:44:08 +01005639 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005640 err_code |= ERR_ALERT | ERR_FATAL;
5641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005642 }
Willy Tarreau93893792009-07-23 13:19:11 +02005643 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005644 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005645 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005646}
5647
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005648int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005649cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
5650{
5651#ifdef CONFIG_HAP_NS
5652 const char *err;
5653 const char *item = args[0];
5654
5655 if (!strcmp(item, "namespace_list")) {
5656 return 0;
5657 }
5658 else if (!strcmp(item, "namespace")) {
5659 size_t idx = 1;
5660 const char *current;
5661 while (*(current = args[idx++])) {
5662 err = invalid_char(current);
5663 if (err) {
5664 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5665 file, linenum, *err, item, current);
5666 return ERR_ALERT | ERR_FATAL;
5667 }
5668
5669 if (netns_store_lookup(current, strlen(current))) {
5670 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
5671 file, linenum, current);
5672 return ERR_ALERT | ERR_FATAL;
5673 }
5674 if (!netns_store_insert(current)) {
5675 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
5676 file, linenum, current);
5677 return ERR_ALERT | ERR_FATAL;
5678 }
5679 }
5680 }
5681
5682 return 0;
5683#else
5684 Alert("parsing [%s:%d]: namespace support is not compiled in.",
5685 file, linenum);
5686 return ERR_ALERT | ERR_FATAL;
5687#endif
5688}
5689
5690int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005691cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5692{
5693
5694 int err_code = 0;
5695 const char *err;
5696
5697 if (!strcmp(args[0], "userlist")) { /* new userlist */
5698 struct userlist *newul;
5699
5700 if (!*args[1]) {
5701 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5702 file, linenum, args[0]);
5703 err_code |= ERR_ALERT | ERR_FATAL;
5704 goto out;
5705 }
5706
5707 err = invalid_char(args[1]);
5708 if (err) {
5709 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5710 file, linenum, *err, args[0], args[1]);
5711 err_code |= ERR_ALERT | ERR_FATAL;
5712 goto out;
5713 }
5714
5715 for (newul = userlist; newul; newul = newul->next)
5716 if (!strcmp(newul->name, args[1])) {
5717 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5718 file, linenum, args[1]);
5719 err_code |= ERR_WARN;
5720 goto out;
5721 }
5722
5723 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5724 if (!newul) {
5725 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5726 err_code |= ERR_ALERT | ERR_ABORT;
5727 goto out;
5728 }
5729
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005730 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005731 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005732 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5733 err_code |= ERR_ALERT | ERR_ABORT;
5734 goto out;
5735 }
5736
5737 newul->next = userlist;
5738 userlist = newul;
5739
5740 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005741 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005742 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005743 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005744
5745 if (!*args[1]) {
5746 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5747 file, linenum, args[0]);
5748 err_code |= ERR_ALERT | ERR_FATAL;
5749 goto out;
5750 }
5751
5752 err = invalid_char(args[1]);
5753 if (err) {
5754 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5755 file, linenum, *err, args[0], args[1]);
5756 err_code |= ERR_ALERT | ERR_FATAL;
5757 goto out;
5758 }
5759
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005760 for (ag = userlist->groups; ag; ag = ag->next)
5761 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005762 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5763 file, linenum, args[1], userlist->name);
5764 err_code |= ERR_ALERT;
5765 goto out;
5766 }
5767
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005768 ag = calloc(1, sizeof(*ag));
5769 if (!ag) {
5770 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5771 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005772 goto out;
5773 }
5774
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005775 ag->name = strdup(args[1]);
5776 if (!ag) {
5777 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5778 err_code |= ERR_ALERT | ERR_ABORT;
5779 goto out;
5780 }
5781
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005782 cur_arg = 2;
5783
5784 while (*args[cur_arg]) {
5785 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005786 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005787 cur_arg += 2;
5788 continue;
5789 } else {
5790 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5791 file, linenum, args[0]);
5792 err_code |= ERR_ALERT | ERR_FATAL;
5793 goto out;
5794 }
5795 }
5796
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005797 ag->next = userlist->groups;
5798 userlist->groups = ag;
5799
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005800 } else if (!strcmp(args[0], "user")) { /* new user */
5801 struct auth_users *newuser;
5802 int cur_arg;
5803
5804 if (!*args[1]) {
5805 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5806 file, linenum, args[0]);
5807 err_code |= ERR_ALERT | ERR_FATAL;
5808 goto out;
5809 }
5810
5811 for (newuser = userlist->users; newuser; newuser = newuser->next)
5812 if (!strcmp(newuser->user, args[1])) {
5813 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5814 file, linenum, args[1], userlist->name);
5815 err_code |= ERR_ALERT;
5816 goto out;
5817 }
5818
5819 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5820 if (!newuser) {
5821 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5822 err_code |= ERR_ALERT | ERR_ABORT;
5823 goto out;
5824 }
5825
5826 newuser->user = strdup(args[1]);
5827
5828 newuser->next = userlist->users;
5829 userlist->users = newuser;
5830
5831 cur_arg = 2;
5832
5833 while (*args[cur_arg]) {
5834 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02005835#ifdef CONFIG_HAP_CRYPT
5836 if (!crypt("", args[cur_arg + 1])) {
5837 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
5838 file, linenum, newuser->user);
5839 err_code |= ERR_ALERT | ERR_FATAL;
5840 goto out;
5841 }
5842#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005843 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5844 file, linenum);
5845 err_code |= ERR_ALERT;
5846#endif
5847 newuser->pass = strdup(args[cur_arg + 1]);
5848 cur_arg += 2;
5849 continue;
5850 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5851 newuser->pass = strdup(args[cur_arg + 1]);
5852 newuser->flags |= AU_O_INSECURE;
5853 cur_arg += 2;
5854 continue;
5855 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005856 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005857 cur_arg += 2;
5858 continue;
5859 } else {
5860 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5861 file, linenum, args[0]);
5862 err_code |= ERR_ALERT | ERR_FATAL;
5863 goto out;
5864 }
5865 }
5866 } else {
5867 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5868 err_code |= ERR_ALERT | ERR_FATAL;
5869 }
5870
5871out:
5872 return err_code;
5873}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005874
5875/*
5876 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005877 * Returns the error code, 0 if OK, or any combination of :
5878 * - ERR_ABORT: must abort ASAP
5879 * - ERR_FATAL: we can continue parsing but not start the service
5880 * - ERR_WARN: a warning has been emitted
5881 * - ERR_ALERT: an alert has been emitted
5882 * Only the two first ones can stop processing, the two others are just
5883 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005884 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005885int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005886{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005887 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005888 FILE *f;
5889 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005890 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005891 struct cfg_section *cs = NULL;
5892 struct cfg_section *ics;
5893
5894 /* Register internal sections */
5895 if (!cfg_register_section("listen", cfg_parse_listen) ||
5896 !cfg_register_section("frontend", cfg_parse_listen) ||
5897 !cfg_register_section("backend", cfg_parse_listen) ||
5898 !cfg_register_section("ruleset", cfg_parse_listen) ||
5899 !cfg_register_section("defaults", cfg_parse_listen) ||
5900 !cfg_register_section("global", cfg_parse_global) ||
5901 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005902 !cfg_register_section("peers", cfg_parse_peers) ||
5903 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005904 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005905
Willy Tarreaubaaee002006-06-26 02:48:02 +02005906 if ((f=fopen(file,"r")) == NULL)
5907 return -1;
5908
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005909 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005910 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005911 char *end;
5912 char *args[MAX_LINE_ARGS + 1];
5913 char *line = thisline;
5914
Willy Tarreaubaaee002006-06-26 02:48:02 +02005915 linenum++;
5916
5917 end = line + strlen(line);
5918
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005919 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5920 /* Check if we reached the limit and the last char is not \n.
5921 * Watch out for the last line without the terminating '\n'!
5922 */
5923 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005924 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005925 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005926 }
5927
Willy Tarreaubaaee002006-06-26 02:48:02 +02005928 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005929 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005930 line++;
5931
5932 arg = 0;
5933 args[arg] = line;
5934
5935 while (*line && arg < MAX_LINE_ARGS) {
5936 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5937 * C equivalent value. Other combinations left unchanged (eg: \1).
5938 */
5939 if (*line == '\\') {
5940 int skip = 0;
5941 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5942 *line = line[1];
5943 skip = 1;
5944 }
5945 else if (line[1] == 'r') {
5946 *line = '\r';
5947 skip = 1;
5948 }
5949 else if (line[1] == 'n') {
5950 *line = '\n';
5951 skip = 1;
5952 }
5953 else if (line[1] == 't') {
5954 *line = '\t';
5955 skip = 1;
5956 }
5957 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005958 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005959 unsigned char hex1, hex2;
5960 hex1 = toupper(line[2]) - '0';
5961 hex2 = toupper(line[3]) - '0';
5962 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5963 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5964 *line = (hex1<<4) + hex2;
5965 skip = 3;
5966 }
5967 else {
5968 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005969 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005970 }
5971 }
5972 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005973 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005974 end -= skip;
5975 }
5976 line++;
5977 }
5978 else if (*line == '#' || *line == '\n' || *line == '\r') {
5979 /* end of string, end of loop */
5980 *line = 0;
5981 break;
5982 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005983 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005984 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005985 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005986 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005987 line++;
5988 args[++arg] = line;
5989 }
5990 else {
5991 line++;
5992 }
5993 }
5994
5995 /* empty line */
5996 if (!**args)
5997 continue;
5998
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005999 if (*line) {
6000 /* we had to stop due to too many args.
6001 * Let's terminate the string, print the offending part then cut the
6002 * last arg.
6003 */
6004 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6005 line++;
6006 *line = '\0';
6007
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006008 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006009 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006010 err_code |= ERR_ALERT | ERR_FATAL;
6011 args[arg] = line;
6012 }
6013
Willy Tarreau540abe42007-05-02 20:50:16 +02006014 /* zero out remaining args and ensure that at least one entry
6015 * is zeroed out.
6016 */
6017 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006018 args[arg] = line;
6019 }
6020
Willy Tarreau3842f002009-06-14 11:39:52 +02006021 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006022 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006023 char *tmp;
6024
Willy Tarreau3842f002009-06-14 11:39:52 +02006025 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006026 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006027 for (arg=0; *args[arg+1]; arg++)
6028 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006029 *tmp = '\0'; // fix the next arg to \0
6030 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006031 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006032 else if (!strcmp(args[0], "default")) {
6033 kwm = KWM_DEF;
6034 for (arg=0; *args[arg+1]; arg++)
6035 args[arg] = args[arg+1]; // shift args after inversion
6036 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006037
William Lallemand0f99e342011-10-12 17:50:54 +02006038 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6039 strcmp(args[0], "log") != 0) {
6040 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006041 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006042 }
6043
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006044 /* detect section start */
6045 list_for_each_entry(ics, &sections, list) {
6046 if (strcmp(args[0], ics->section_name) == 0) {
6047 cursection = ics->section_name;
6048 cs = ics;
6049 break;
6050 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006051 }
6052
Willy Tarreaubaaee002006-06-26 02:48:02 +02006053 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006054 if (cs)
6055 err_code |= cs->section_parser(file, linenum, args, kwm);
6056 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006057 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006058 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006059 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006060
6061 if (err_code & ERR_ABORT)
6062 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006063 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006064 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006065 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006066 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006067}
6068
Willy Tarreau64ab6072014-09-16 12:17:36 +02006069/* This function propagates processes from frontend <from> to backend <to> so
6070 * that it is always guaranteed that a backend pointed to by a frontend is
6071 * bound to all of its processes. After that, if the target is a "listen"
6072 * instance, the function recursively descends the target's own targets along
6073 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6074 * checked first to ensure that <to> is already bound to all processes of
6075 * <from>, there is no risk of looping and we ensure to follow the shortest
6076 * path to the destination.
6077 *
6078 * It is possible to set <to> to NULL for the first call so that the function
6079 * takes care of visiting the initial frontend in <from>.
6080 *
6081 * It is important to note that the function relies on the fact that all names
6082 * have already been resolved.
6083 */
6084void propagate_processes(struct proxy *from, struct proxy *to)
6085{
6086 struct switching_rule *rule;
6087 struct hdr_exp *exp;
6088
6089 if (to) {
6090 /* check whether we need to go down */
6091 if (from->bind_proc &&
6092 (from->bind_proc & to->bind_proc) == from->bind_proc)
6093 return;
6094
6095 if (!from->bind_proc && !to->bind_proc)
6096 return;
6097
6098 to->bind_proc = from->bind_proc ?
6099 (to->bind_proc | from->bind_proc) : 0;
6100
6101 /* now propagate down */
6102 from = to;
6103 }
6104
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006105 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006106 return;
6107
Willy Tarreauf6b70012014-12-18 14:00:43 +01006108 if (from->state == PR_STSTOPPED)
6109 return;
6110
Willy Tarreau64ab6072014-09-16 12:17:36 +02006111 /* default_backend */
6112 if (from->defbe.be)
6113 propagate_processes(from, from->defbe.be);
6114
6115 /* use_backend */
6116 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006117 if (rule->dynamic)
6118 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006119 to = rule->be.backend;
6120 propagate_processes(from, to);
6121 }
6122
6123 /* reqsetbe */
6124 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6125 if (exp->action != ACT_SETBE)
6126 continue;
6127 to = (struct proxy *)exp->replace;
6128 propagate_processes(from, to);
6129 }
6130}
6131
Willy Tarreaubb925012009-07-23 13:36:36 +02006132/*
6133 * Returns the error code, 0 if OK, or any combination of :
6134 * - ERR_ABORT: must abort ASAP
6135 * - ERR_FATAL: we can continue parsing but not start the service
6136 * - ERR_WARN: a warning has been emitted
6137 * - ERR_ALERT: an alert has been emitted
6138 * Only the two first ones can stop processing, the two others are just
6139 * indicators.
6140 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006141int check_config_validity()
6142{
6143 int cfgerr = 0;
6144 struct proxy *curproxy = NULL;
6145 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006146 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006147 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006148 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006149
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006150 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006151 /*
6152 * Now, check for the integrity of all that we have collected.
6153 */
6154
6155 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006156 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006157
Willy Tarreau193b8c62012-11-22 00:17:38 +01006158 if (!global.tune.max_http_hdr)
6159 global.tune.max_http_hdr = MAX_HTTP_HDR;
6160
6161 if (!global.tune.cookie_len)
6162 global.tune.cookie_len = CAPTURE_LEN;
6163
6164 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6165
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006166 /* Post initialisation of the users and groups lists. */
6167 err_code = userlist_postinit();
6168 if (err_code != ERR_NONE)
6169 goto out;
6170
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006171 /* first, we will invert the proxy list order */
6172 curproxy = NULL;
6173 while (proxy) {
6174 struct proxy *next;
6175
6176 next = proxy->next;
6177 proxy->next = curproxy;
6178 curproxy = proxy;
6179 if (!next)
6180 break;
6181 proxy = next;
6182 }
6183
Willy Tarreau419ead82014-09-16 13:41:21 +02006184 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006185 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006186 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006187 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006188 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006189 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006190 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006191 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006192
Willy Tarreau050536d2012-10-04 08:47:34 +02006193 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006194 /* proxy ID not set, use automatic numbering with first
6195 * spare entry starting with next_pxid.
6196 */
6197 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6198 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6199 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006200 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006201 next_pxid++;
6202
Willy Tarreau55ea7572007-06-17 19:56:27 +02006203
Willy Tarreaubaaee002006-06-26 02:48:02 +02006204 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006205 /* ensure we don't keep listeners uselessly bound */
6206 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006207 continue;
6208 }
6209
Willy Tarreau102df612014-05-07 23:56:38 +02006210 /* Check multi-process mode compatibility for the current proxy */
6211
6212 if (curproxy->bind_proc) {
6213 /* an explicit bind-process was specified, let's check how many
6214 * processes remain.
6215 */
6216 nbproc = popcount(curproxy->bind_proc);
6217
6218 curproxy->bind_proc &= nbits(global.nbproc);
6219 if (!curproxy->bind_proc && nbproc == 1) {
6220 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);
6221 curproxy->bind_proc = 1;
6222 }
6223 else if (!curproxy->bind_proc && nbproc > 1) {
6224 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);
6225 curproxy->bind_proc = 0;
6226 }
6227 }
6228
Willy Tarreau3d209582014-05-09 17:06:11 +02006229 /* check and reduce the bind-proc of each listener */
6230 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6231 unsigned long mask;
6232
6233 if (!bind_conf->bind_proc)
6234 continue;
6235
6236 mask = nbits(global.nbproc);
6237 if (curproxy->bind_proc)
6238 mask &= curproxy->bind_proc;
6239 /* mask cannot be null here thanks to the previous checks */
6240
6241 nbproc = popcount(bind_conf->bind_proc);
6242 bind_conf->bind_proc &= mask;
6243
6244 if (!bind_conf->bind_proc && nbproc == 1) {
6245 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",
6246 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6247 bind_conf->bind_proc = mask & ~(mask - 1);
6248 }
6249 else if (!bind_conf->bind_proc && nbproc > 1) {
6250 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",
6251 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6252 bind_conf->bind_proc = 0;
6253 }
6254 }
6255
Willy Tarreau102df612014-05-07 23:56:38 +02006256 if (global.nbproc > 1 && curproxy->table.peers.name) {
6257 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6258 curproxy->id);
6259 cfgerr++;
6260 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006261
Willy Tarreauff01a212009-03-15 13:46:16 +01006262 switch (curproxy->mode) {
6263 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006264 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006265 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006266 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6267 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006268 cfgerr++;
6269 }
6270
6271 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006272 Warning("config : servers will be ignored for %s '%s'.\n",
6273 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006274 break;
6275
6276 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006277 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006278 break;
6279
6280 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006281 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006282 break;
6283 }
6284
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006285 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006286 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006287 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006288 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6289 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006290 cfgerr++;
6291 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006292#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006293 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006294 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6295 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006296 cfgerr++;
6297 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006298#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006299 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006300 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6301 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006302 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006303 }
6304 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006305 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006306 /* If no LB algo is set in a backend, and we're not in
6307 * transparent mode, dispatch mode nor proxy mode, we
6308 * want to use balance roundrobin by default.
6309 */
6310 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6311 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006312 }
6313 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006314
Willy Tarreau1620ec32011-08-06 17:05:02 +02006315 if (curproxy->options & PR_O_DISPATCH)
6316 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6317 else if (curproxy->options & PR_O_HTTP_PROXY)
6318 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6319 else if (curproxy->options & PR_O_TRANSP)
6320 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006321
Willy Tarreau1620ec32011-08-06 17:05:02 +02006322 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6323 if (curproxy->options & PR_O_DISABLE404) {
6324 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6325 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6326 err_code |= ERR_WARN;
6327 curproxy->options &= ~PR_O_DISABLE404;
6328 }
6329 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6330 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6331 "send-state", proxy_type_str(curproxy), curproxy->id);
6332 err_code |= ERR_WARN;
6333 curproxy->options &= ~PR_O2_CHK_SNDST;
6334 }
Willy Tarreauef781042010-01-27 11:53:01 +01006335 }
6336
Simon Horman98637e52014-06-20 12:30:16 +09006337 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6338 if (!global.external_check) {
6339 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6340 curproxy->id, "option external-check");
6341 cfgerr++;
6342 }
6343 if (!curproxy->check_command) {
6344 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6345 curproxy->id, "option external-check");
6346 cfgerr++;
6347 }
6348 }
6349
6350 if (curproxy->check_command) {
6351 int clear = 0;
6352 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6353 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6354 "external-check command", proxy_type_str(curproxy), curproxy->id);
6355 err_code |= ERR_WARN;
6356 clear = 1;
6357 }
6358 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6359 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6360 curproxy->id, "external-check command");
6361 cfgerr++;
6362 }
6363 if (clear) {
6364 free(curproxy->check_command);
6365 curproxy->check_command = NULL;
6366 }
6367 }
6368
6369 if (curproxy->check_path) {
6370 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6371 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6372 "external-check path", proxy_type_str(curproxy), curproxy->id);
6373 err_code |= ERR_WARN;
6374 free(curproxy->check_path);
6375 curproxy->check_path = NULL;
6376 }
6377 }
6378
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006379 /* if a default backend was specified, let's find it */
6380 if (curproxy->defbe.name) {
6381 struct proxy *target;
6382
Alex Williams96532db2009-11-01 21:27:13 -05006383 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006384 if (!target) {
6385 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6386 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006387 cfgerr++;
6388 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006389 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6390 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006391 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006392 } else {
6393 free(curproxy->defbe.name);
6394 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006395
6396 /* Emit a warning if this proxy also has some servers */
6397 if (curproxy->srv) {
6398 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6399 curproxy->id);
6400 err_code |= ERR_WARN;
6401 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006402 }
6403 }
6404
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006405 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006406 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6407 /* map jump target for ACT_SETBE in req_rep chain */
6408 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006409 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006410 struct proxy *target;
6411
Willy Tarreaua496b602006-12-17 23:15:24 +01006412 if (exp->action != ACT_SETBE)
6413 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006414
Alex Williams96532db2009-11-01 21:27:13 -05006415 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006416 if (!target) {
6417 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6418 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006419 cfgerr++;
6420 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006421 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6422 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006423 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006424 } else {
6425 free((void *)exp->replace);
6426 exp->replace = (const char *)target;
6427 }
6428 }
6429 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006430
6431 /* find the target proxy for 'use_backend' rules */
6432 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006433 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006434 struct logformat_node *node;
6435 char *pxname;
6436
6437 /* Try to parse the string as a log format expression. If the result
6438 * of the parsing is only one entry containing a simple string, then
6439 * it's a standard string corresponding to a static rule, thus the
6440 * parsing is cancelled and be.name is restored to be resolved.
6441 */
6442 pxname = rule->be.name;
6443 LIST_INIT(&rule->be.expr);
6444 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6445 curproxy->conf.args.file, curproxy->conf.args.line);
6446 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6447
6448 if (!LIST_ISEMPTY(&rule->be.expr)) {
6449 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6450 rule->dynamic = 1;
6451 free(pxname);
6452 continue;
6453 }
6454 /* simple string: free the expression and fall back to static rule */
6455 free(node->arg);
6456 free(node);
6457 }
6458
6459 rule->dynamic = 0;
6460 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006461
Alex Williams96532db2009-11-01 21:27:13 -05006462 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006463
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006464 if (!target) {
6465 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6466 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006467 cfgerr++;
6468 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006469 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6470 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006471 cfgerr++;
6472 } else {
6473 free((void *)rule->be.name);
6474 rule->be.backend = target;
6475 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006476 }
6477
Willy Tarreau64ab6072014-09-16 12:17:36 +02006478 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006479 list_for_each_entry(srule, &curproxy->server_rules, list) {
6480 struct server *target = findserver(curproxy, srule->srv.name);
6481
6482 if (!target) {
6483 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6484 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6485 cfgerr++;
6486 continue;
6487 }
6488 free((void *)srule->srv.name);
6489 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006490 }
6491
Emeric Brunb982a3d2010-01-04 15:45:53 +01006492 /* find the target table for 'stick' rules */
6493 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6494 struct proxy *target;
6495
Emeric Brun1d33b292010-01-04 15:47:17 +01006496 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6497 if (mrule->flags & STK_IS_STORE)
6498 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6499
Emeric Brunb982a3d2010-01-04 15:45:53 +01006500 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006501 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006502 else
6503 target = curproxy;
6504
6505 if (!target) {
6506 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6507 curproxy->id, mrule->table.name);
6508 cfgerr++;
6509 }
6510 else if (target->table.size == 0) {
6511 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6512 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6513 cfgerr++;
6514 }
Willy Tarreau12785782012-04-27 21:37:17 +02006515 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6516 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006517 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6518 cfgerr++;
6519 }
6520 else {
6521 free((void *)mrule->table.name);
6522 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006523 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006524 }
6525 }
6526
6527 /* find the target table for 'store response' rules */
6528 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6529 struct proxy *target;
6530
Emeric Brun1d33b292010-01-04 15:47:17 +01006531 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6532
Emeric Brunb982a3d2010-01-04 15:45:53 +01006533 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006534 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006535 else
6536 target = curproxy;
6537
6538 if (!target) {
6539 Alert("Proxy '%s': unable to find store table '%s'.\n",
6540 curproxy->id, mrule->table.name);
6541 cfgerr++;
6542 }
6543 else if (target->table.size == 0) {
6544 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6545 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6546 cfgerr++;
6547 }
Willy Tarreau12785782012-04-27 21:37:17 +02006548 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6549 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006550 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6551 cfgerr++;
6552 }
6553 else {
6554 free((void *)mrule->table.name);
6555 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006556 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006557 }
6558 }
6559
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006560 /* find the target table for 'tcp-request' layer 4 rules */
6561 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6562 struct proxy *target;
6563
Willy Tarreaub4c84932013-07-23 19:15:30 +02006564 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006565 continue;
6566
6567 if (trule->act_prm.trk_ctr.table.n)
6568 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6569 else
6570 target = curproxy;
6571
6572 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006573 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6574 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006575 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006576 cfgerr++;
6577 }
6578 else if (target->table.size == 0) {
6579 Alert("Proxy '%s': table '%s' used but not configured.\n",
6580 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6581 cfgerr++;
6582 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006583 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6584 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6585 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 +01006586 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006587 cfgerr++;
6588 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006589 else {
6590 free(trule->act_prm.trk_ctr.table.n);
6591 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006592 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006593 * to pass a list of counters to track and allocate them right here using
6594 * stktable_alloc_data_type().
6595 */
6596 }
6597 }
6598
Willy Tarreaud1f96522010-08-03 19:34:32 +02006599 /* find the target table for 'tcp-request' layer 6 rules */
6600 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6601 struct proxy *target;
6602
Willy Tarreaub4c84932013-07-23 19:15:30 +02006603 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006604 continue;
6605
6606 if (trule->act_prm.trk_ctr.table.n)
6607 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6608 else
6609 target = curproxy;
6610
6611 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006612 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6613 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006614 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006615 cfgerr++;
6616 }
6617 else if (target->table.size == 0) {
6618 Alert("Proxy '%s': table '%s' used but not configured.\n",
6619 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6620 cfgerr++;
6621 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006622 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6623 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6624 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 +01006625 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006626 cfgerr++;
6627 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006628 else {
6629 free(trule->act_prm.trk_ctr.table.n);
6630 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006631 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006632 * to pass a list of counters to track and allocate them right here using
6633 * stktable_alloc_data_type().
6634 */
6635 }
6636 }
6637
Willy Tarreau09448f72014-06-25 18:12:15 +02006638 /* find the target table for 'http-request' layer 7 rules */
6639 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6640 struct proxy *target;
6641
6642 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6643 continue;
6644
6645 if (hrqrule->act_prm.trk_ctr.table.n)
6646 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6647 else
6648 target = curproxy;
6649
6650 if (!target) {
6651 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6652 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6653 http_req_trk_idx(hrqrule->action));
6654 cfgerr++;
6655 }
6656 else if (target->table.size == 0) {
6657 Alert("Proxy '%s': table '%s' used but not configured.\n",
6658 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6659 cfgerr++;
6660 }
6661 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6662 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6663 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6664 http_req_trk_idx(hrqrule->action));
6665 cfgerr++;
6666 }
6667 else {
6668 free(hrqrule->act_prm.trk_ctr.table.n);
6669 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6670 /* Note: if we decide to enhance the track-sc syntax, we may be able
6671 * to pass a list of counters to track and allocate them right here using
6672 * stktable_alloc_data_type().
6673 */
6674 }
6675 }
6676
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006677 /* move any "block" rules at the beginning of the http-request rules */
6678 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6679 /* insert block_rules into http_req_rules at the beginning */
6680 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6681 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6682 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6683 curproxy->http_req_rules.n = curproxy->block_rules.n;
6684 LIST_INIT(&curproxy->block_rules);
6685 }
6686
Emeric Brun32da3c42010-09-23 18:39:19 +02006687 if (curproxy->table.peers.name) {
6688 struct peers *curpeers = peers;
6689
6690 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6691 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6692 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006693 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006694 break;
6695 }
6696 }
6697
6698 if (!curpeers) {
6699 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6700 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006701 free((void *)curproxy->table.peers.name);
6702 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006703 cfgerr++;
6704 }
6705 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006706 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6707 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006708 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006709 cfgerr++;
6710 }
6711 }
6712
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006713 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006714 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006715 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6716 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6717 "proxy", curproxy->id);
6718 cfgerr++;
6719 goto out_uri_auth_compat;
6720 }
6721
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006722 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006723 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006724 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006725 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006726
Willy Tarreau95fa4692010-02-01 13:05:50 +01006727 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6728 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006729
6730 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006731 uri_auth_compat_req[i++] = "realm";
6732 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6733 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006734
Willy Tarreau95fa4692010-02-01 13:05:50 +01006735 uri_auth_compat_req[i++] = "unless";
6736 uri_auth_compat_req[i++] = "{";
6737 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6738 uri_auth_compat_req[i++] = "}";
6739 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006740
Willy Tarreauff011f22011-01-06 17:51:27 +01006741 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6742 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006743 cfgerr++;
6744 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006745 }
6746
Willy Tarreauff011f22011-01-06 17:51:27 +01006747 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006748
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006749 if (curproxy->uri_auth->auth_realm) {
6750 free(curproxy->uri_auth->auth_realm);
6751 curproxy->uri_auth->auth_realm = NULL;
6752 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006753
6754 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006755 }
6756out_uri_auth_compat:
6757
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006758 /* compile the log format */
6759 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006760 if (curproxy->conf.logformat_string != default_http_log_format &&
6761 curproxy->conf.logformat_string != default_tcp_log_format &&
6762 curproxy->conf.logformat_string != clf_http_log_format)
6763 free(curproxy->conf.logformat_string);
6764 curproxy->conf.logformat_string = NULL;
6765 free(curproxy->conf.lfs_file);
6766 curproxy->conf.lfs_file = NULL;
6767 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006768 }
6769
Willy Tarreau62a61232013-04-12 18:13:46 +02006770 if (curproxy->conf.logformat_string) {
6771 curproxy->conf.args.ctx = ARGC_LOG;
6772 curproxy->conf.args.file = curproxy->conf.lfs_file;
6773 curproxy->conf.args.line = curproxy->conf.lfs_line;
6774 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006775 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006776 curproxy->conf.args.file = NULL;
6777 curproxy->conf.args.line = 0;
6778 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006779
Willy Tarreau62a61232013-04-12 18:13:46 +02006780 if (curproxy->conf.uniqueid_format_string) {
6781 curproxy->conf.args.ctx = ARGC_UIF;
6782 curproxy->conf.args.file = curproxy->conf.uif_file;
6783 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006784 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08006785 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006786 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006787 curproxy->conf.args.file = NULL;
6788 curproxy->conf.args.line = 0;
6789 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006790
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006791 /* only now we can check if some args remain unresolved.
6792 * This must be done after the users and groups resolution.
6793 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006794 cfgerr += smp_resolve_args(curproxy);
6795 if (!cfgerr)
6796 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006797
Willy Tarreau2738a142006-07-08 17:28:09 +02006798 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006799 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006800 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006801 (!curproxy->timeout.connect ||
6802 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006803 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006804 " | While not properly invalid, you will certainly encounter various problems\n"
6805 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006806 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006807 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006808 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006809 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006810
Willy Tarreau1fa31262007-12-03 00:36:16 +01006811 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6812 * We must still support older configurations, so let's find out whether those
6813 * parameters have been set or must be copied from contimeouts.
6814 */
6815 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006816 if (!curproxy->timeout.tarpit ||
6817 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006818 /* tarpit timeout not set. We search in the following order:
6819 * default.tarpit, curr.connect, default.connect.
6820 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006821 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006822 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006823 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006824 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006825 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006826 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006827 }
6828 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006829 (!curproxy->timeout.queue ||
6830 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006831 /* queue timeout not set. We search in the following order:
6832 * default.queue, curr.connect, default.connect.
6833 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006834 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006835 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006836 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006837 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006838 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006839 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006840 }
6841 }
6842
Willy Tarreau1620ec32011-08-06 17:05:02 +02006843 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006844 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6845 curproxy->check_req = (char *)malloc(curproxy->check_len);
6846 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006847 }
6848
Willy Tarreau215663d2014-06-13 18:30:23 +02006849 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6850 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6851 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6852 proxy_type_str(curproxy), curproxy->id);
6853 err_code |= ERR_WARN;
6854 }
6855
Willy Tarreau193b8c62012-11-22 00:17:38 +01006856 /* ensure that cookie capture length is not too large */
6857 if (curproxy->capture_len >= global.tune.cookie_len) {
6858 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6859 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6860 err_code |= ERR_WARN;
6861 curproxy->capture_len = global.tune.cookie_len - 1;
6862 }
6863
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006864 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006865 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006866 curproxy->req_cap_pool = create_pool("ptrcap",
6867 curproxy->nb_req_cap * sizeof(char *),
6868 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006869 }
6870
6871 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006872 curproxy->rsp_cap_pool = create_pool("ptrcap",
6873 curproxy->nb_rsp_cap * sizeof(char *),
6874 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006875 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006876
Willy Tarreaubaaee002006-06-26 02:48:02 +02006877 /* first, we will invert the servers list order */
6878 newsrv = NULL;
6879 while (curproxy->srv) {
6880 struct server *next;
6881
6882 next = curproxy->srv->next;
6883 curproxy->srv->next = newsrv;
6884 newsrv = curproxy->srv;
6885 if (!next)
6886 break;
6887 curproxy->srv = next;
6888 }
6889
Willy Tarreau17edc812014-01-03 12:14:34 +01006890 /* Check that no server name conflicts. This causes trouble in the stats.
6891 * We only emit a warning for the first conflict affecting each server,
6892 * in order to avoid combinatory explosion if all servers have the same
6893 * name. We do that only for servers which do not have an explicit ID,
6894 * because these IDs were made also for distinguishing them and we don't
6895 * want to annoy people who correctly manage them.
6896 */
6897 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6898 struct server *other_srv;
6899
6900 if (newsrv->puid)
6901 continue;
6902
6903 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6904 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6905 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6906 newsrv->conf.file, newsrv->conf.line,
6907 proxy_type_str(curproxy), curproxy->id,
6908 newsrv->id, other_srv->conf.line);
6909 break;
6910 }
6911 }
6912 }
6913
Willy Tarreaudd701652010-05-25 23:03:02 +02006914 /* assign automatic UIDs to servers which don't have one yet */
6915 next_id = 1;
6916 newsrv = curproxy->srv;
6917 while (newsrv != NULL) {
6918 if (!newsrv->puid) {
6919 /* server ID not set, use automatic numbering with first
6920 * spare entry starting with next_svid.
6921 */
6922 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6923 newsrv->conf.id.key = newsrv->puid = next_id;
6924 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6925 }
6926 next_id++;
6927 newsrv = newsrv->next;
6928 }
6929
Willy Tarreau20697042007-11-15 23:26:18 +01006930 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006931 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006932
Willy Tarreau62c3be22012-01-20 13:12:32 +01006933 /*
6934 * If this server supports a maxconn parameter, it needs a dedicated
6935 * tasks to fill the emptied slots when a connection leaves.
6936 * Also, resolve deferred tracking dependency if needed.
6937 */
6938 newsrv = curproxy->srv;
6939 while (newsrv != NULL) {
6940 if (newsrv->minconn > newsrv->maxconn) {
6941 /* Only 'minconn' was specified, or it was higher than or equal
6942 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6943 * this will avoid further useless expensive computations.
6944 */
6945 newsrv->maxconn = newsrv->minconn;
6946 } else if (newsrv->maxconn && !newsrv->minconn) {
6947 /* minconn was not specified, so we set it to maxconn */
6948 newsrv->minconn = newsrv->maxconn;
6949 }
6950
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006951#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006952 if (newsrv->use_ssl || newsrv->check.use_ssl)
6953 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006954#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006955
Willy Tarreau2f075e92013-12-03 11:11:34 +01006956 /* set the check type on the server */
6957 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6958
Willy Tarreau62c3be22012-01-20 13:12:32 +01006959 if (newsrv->trackit) {
6960 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006961 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006962 char *pname, *sname;
6963
6964 pname = newsrv->trackit;
6965 sname = strrchr(pname, '/');
6966
6967 if (sname)
6968 *sname++ = '\0';
6969 else {
6970 sname = pname;
6971 pname = NULL;
6972 }
6973
6974 if (pname) {
6975 px = findproxy(pname, PR_CAP_BE);
6976 if (!px) {
6977 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6978 proxy_type_str(curproxy), curproxy->id,
6979 newsrv->id, pname);
6980 cfgerr++;
6981 goto next_srv;
6982 }
6983 } else
6984 px = curproxy;
6985
6986 srv = findserver(px, sname);
6987 if (!srv) {
6988 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6989 proxy_type_str(curproxy), curproxy->id,
6990 newsrv->id, sname);
6991 cfgerr++;
6992 goto next_srv;
6993 }
6994
Willy Tarreau32091232014-05-16 13:52:00 +02006995 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6996 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6997 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006998 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006999 "tracking as it does not have any check nor agent enabled.\n",
7000 proxy_type_str(curproxy), curproxy->id,
7001 newsrv->id, px->id, srv->id);
7002 cfgerr++;
7003 goto next_srv;
7004 }
7005
7006 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7007
7008 if (loop) {
7009 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7010 "belongs to a tracking chain looping back to %s/%s.\n",
7011 proxy_type_str(curproxy), curproxy->id,
7012 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007013 cfgerr++;
7014 goto next_srv;
7015 }
7016
7017 if (curproxy != px &&
7018 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7019 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7020 "tracking: disable-on-404 option inconsistency.\n",
7021 proxy_type_str(curproxy), curproxy->id,
7022 newsrv->id, px->id, srv->id);
7023 cfgerr++;
7024 goto next_srv;
7025 }
7026
7027 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007028 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007029 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007030 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007031 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09007032 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007033 }
7034
7035 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007036 newsrv->tracknext = srv->trackers;
7037 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007038
7039 free(newsrv->trackit);
7040 newsrv->trackit = NULL;
7041 }
7042 next_srv:
7043 newsrv = newsrv->next;
7044 }
7045
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007046 /* We have to initialize the server lookup mechanism depending
7047 * on what LB algorithm was choosen.
7048 */
7049
7050 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7051 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7052 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007053 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7054 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7055 init_server_map(curproxy);
7056 } else {
7057 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7058 fwrr_init_server_groups(curproxy);
7059 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007060 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007061
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007062 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007063 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7064 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7065 fwlc_init_server_tree(curproxy);
7066 } else {
7067 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7068 fas_init_server_tree(curproxy);
7069 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007070 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007071
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007072 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007073 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7074 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7075 chash_init_server_tree(curproxy);
7076 } else {
7077 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7078 init_server_map(curproxy);
7079 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007080 break;
7081 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007082
7083 if (curproxy->options & PR_O_LOGASAP)
7084 curproxy->to_log &= ~LW_BYTES;
7085
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007086 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007087 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007088 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7089 proxy_type_str(curproxy), curproxy->id);
7090 err_code |= ERR_WARN;
7091 }
7092
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007093 if (curproxy->mode != PR_MODE_HTTP) {
7094 int optnum;
7095
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007096 if (curproxy->uri_auth) {
7097 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7098 proxy_type_str(curproxy), curproxy->id);
7099 err_code |= ERR_WARN;
7100 curproxy->uri_auth = NULL;
7101 }
7102
Willy Tarreau87cf5142011-08-19 22:57:24 +02007103 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007104 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7105 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7106 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007107 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007108 }
7109
7110 if (curproxy->options & PR_O_ORGTO) {
7111 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7112 "originalto", proxy_type_str(curproxy), curproxy->id);
7113 err_code |= ERR_WARN;
7114 curproxy->options &= ~PR_O_ORGTO;
7115 }
7116
7117 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7118 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7119 (curproxy->cap & cfg_opts[optnum].cap) &&
7120 (curproxy->options & cfg_opts[optnum].val)) {
7121 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7122 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7123 err_code |= ERR_WARN;
7124 curproxy->options &= ~cfg_opts[optnum].val;
7125 }
7126 }
7127
7128 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7129 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7130 (curproxy->cap & cfg_opts2[optnum].cap) &&
7131 (curproxy->options2 & cfg_opts2[optnum].val)) {
7132 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7133 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7134 err_code |= ERR_WARN;
7135 curproxy->options2 &= ~cfg_opts2[optnum].val;
7136 }
7137 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007138
Pieter Baauwd551fb52013-05-08 22:49:23 +02007139#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007140 if (curproxy->conn_src.bind_hdr_occ) {
7141 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007142 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007143 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007144 err_code |= ERR_WARN;
7145 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007146#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007147 }
7148
Willy Tarreaubaaee002006-06-26 02:48:02 +02007149 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007150 * ensure that we're not cross-dressing a TCP server into HTTP.
7151 */
7152 newsrv = curproxy->srv;
7153 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007154 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007155 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7156 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007157 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007158 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007159
Willy Tarreau0cec3312011-10-31 13:49:26 +01007160 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7161 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7162 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7163 err_code |= ERR_WARN;
7164 }
7165
Willy Tarreauc93cd162014-05-13 15:54:22 +02007166 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007167 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7168 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7169 err_code |= ERR_WARN;
7170 }
7171
Pieter Baauwd551fb52013-05-08 22:49:23 +02007172#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007173 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7174 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007175 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 +01007176 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007177 err_code |= ERR_WARN;
7178 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007179#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007180 newsrv = newsrv->next;
7181 }
7182
Willy Tarreaue42bd962014-09-16 16:21:19 +02007183 /* check if we have a frontend with "tcp-request content" looking at L7
7184 * with no inspect-delay
7185 */
7186 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7187 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7188 if (trule->action == TCP_ACT_CAPTURE &&
7189 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7190 break;
7191 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7192 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7193 break;
7194 }
7195
7196 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7197 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7198 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7199 " This means that these rules will randomly find their contents. This can be fixed by"
7200 " setting the tcp-request inspect-delay.\n",
7201 proxy_type_str(curproxy), curproxy->id);
7202 err_code |= ERR_WARN;
7203 }
7204 }
7205
Willy Tarreauc1a21672009-08-16 22:37:44 +02007206 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007207 if (!curproxy->accept)
7208 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007209
Willy Tarreauc1a21672009-08-16 22:37:44 +02007210 if (curproxy->tcp_req.inspect_delay ||
7211 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007212 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007213
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007214 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007215 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007216 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007217 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007218
7219 /* both TCP and HTTP must check switching rules */
7220 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7221 }
7222
7223 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007224 if (curproxy->tcp_req.inspect_delay ||
7225 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7226 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7227
Emeric Brun97679e72010-09-23 17:56:44 +02007228 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7229 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7230
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007231 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007232 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007233 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007234 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007235
7236 /* If the backend does requires RDP cookie persistence, we have to
7237 * enable the corresponding analyser.
7238 */
7239 if (curproxy->options2 & PR_O2_RDPC_PRST)
7240 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7241 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007242 }
7243
7244 /***********************************************************/
7245 /* At this point, target names have already been resolved. */
7246 /***********************************************************/
7247
7248 /* Check multi-process mode compatibility */
7249
7250 if (global.nbproc > 1 && global.stats_fe) {
7251 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7252 unsigned long mask;
7253
7254 mask = nbits(global.nbproc);
7255 if (global.stats_fe->bind_proc)
7256 mask &= global.stats_fe->bind_proc;
7257
7258 if (bind_conf->bind_proc)
7259 mask &= bind_conf->bind_proc;
7260
7261 /* stop here if more than one process is used */
7262 if (popcount(mask) > 1)
7263 break;
7264 }
7265 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7266 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");
7267 }
7268 }
7269
7270 /* Make each frontend inherit bind-process from its listeners when not specified. */
7271 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7272 if (curproxy->bind_proc)
7273 continue;
7274
7275 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7276 unsigned long mask;
7277
7278 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7279 curproxy->bind_proc |= mask;
7280 }
7281
7282 if (!curproxy->bind_proc)
7283 curproxy->bind_proc = ~0UL;
7284 }
7285
7286 if (global.stats_fe) {
7287 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7288 unsigned long mask;
7289
7290 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7291 global.stats_fe->bind_proc |= mask;
7292 }
7293 if (!global.stats_fe->bind_proc)
7294 global.stats_fe->bind_proc = ~0UL;
7295 }
7296
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007297 /* propagate bindings from frontends to backends. Don't do it if there
7298 * are any fatal errors as we must not call it with unresolved proxies.
7299 */
7300 if (!cfgerr) {
7301 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7302 if (curproxy->cap & PR_CAP_FE)
7303 propagate_processes(curproxy, NULL);
7304 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007305 }
7306
7307 /* Bind each unbound backend to all processes when not specified. */
7308 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7309 if (curproxy->bind_proc)
7310 continue;
7311 curproxy->bind_proc = ~0UL;
7312 }
7313
7314 /*******************************************************/
7315 /* At this step, all proxies have a non-null bind_proc */
7316 /*******************************************************/
7317
7318 /* perform the final checks before creating tasks */
7319
7320 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7321 struct listener *listener;
7322 unsigned int next_id;
7323 int nbproc;
7324
7325 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007326
Emeric Brunc52962f2012-11-15 18:28:02 +01007327#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007328 /* Configure SSL for each bind line.
7329 * Note: if configuration fails at some point, the ->ctx member
7330 * remains NULL so that listeners can later detach.
7331 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007332 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007333 int alloc_ctx;
7334
Emeric Brunc52962f2012-11-15 18:28:02 +01007335 if (!bind_conf->is_ssl) {
7336 if (bind_conf->default_ctx) {
7337 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7338 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7339 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007340 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007341 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007342 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007343 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007344 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007345 cfgerr++;
7346 continue;
7347 }
7348
Emeric Brun8dc60392014-05-09 13:52:00 +02007349 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007350 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007351 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7352 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");
7353 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007354 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007355 cfgerr++;
7356 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007357 }
7358
Emeric Brunfc0421f2012-09-07 17:30:07 +02007359 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007360 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007361 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007362#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007363
Willy Tarreaue6b98942007-10-29 01:09:36 +01007364 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007365 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007366 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007367 if (!listener->luid) {
7368 /* listener ID not set, use automatic numbering with first
7369 * spare entry starting with next_luid.
7370 */
7371 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7372 listener->conf.id.key = listener->luid = next_id;
7373 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007374 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007375 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007376
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007377 /* enable separate counters */
7378 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7379 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007380 if (!listener->name)
7381 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007382 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007383
Willy Tarreaue6b98942007-10-29 01:09:36 +01007384 if (curproxy->options & PR_O_TCP_NOLING)
7385 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007386 if (!listener->maxconn)
7387 listener->maxconn = curproxy->maxconn;
7388 if (!listener->backlog)
7389 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007390 if (!listener->maxaccept)
7391 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7392
7393 /* we want to have an optimal behaviour on single process mode to
7394 * maximize the work at once, but in multi-process we want to keep
7395 * some fairness between processes, so we target half of the max
7396 * number of events to be balanced over all the processes the proxy
7397 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7398 * used to disable the limit.
7399 */
7400 if (listener->maxaccept > 0) {
7401 if (nbproc > 1)
7402 listener->maxaccept = (listener->maxaccept + 1) / 2;
7403 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7404 }
7405
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007406 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007407 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007408 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007409 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007410
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007411 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7412 listener->options |= LI_O_TCP_RULES;
7413
Willy Tarreaude3041d2010-05-31 10:56:17 +02007414 if (curproxy->mon_mask.s_addr)
7415 listener->options |= LI_O_CHK_MONNET;
7416
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007417 /* smart accept mode is automatic in HTTP mode */
7418 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007419 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007420 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7421 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007422 }
7423
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007424 /* Release unused SSL configs */
7425 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7426 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007427 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007428#ifdef USE_OPENSSL
7429 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007430 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007431 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007432 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007433 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007434#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007435 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007436
Willy Tarreau102df612014-05-07 23:56:38 +02007437 if (nbproc > 1) {
7438 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02007439 int count, maxproc = 0;
7440
7441 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7442 count = popcount(bind_conf->bind_proc);
7443 if (count > maxproc)
7444 maxproc = count;
7445 }
7446 /* backends have 0, frontends have 1 or more */
7447 if (maxproc != 1)
7448 Warning("Proxy '%s': in multi-process mode, stats will be"
7449 " limited to process assigned to the current request.\n",
7450 curproxy->id);
7451
Willy Tarreau102df612014-05-07 23:56:38 +02007452 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7453 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7454 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007455 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007456 }
Willy Tarreau102df612014-05-07 23:56:38 +02007457 if (curproxy->appsession_name) {
7458 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7459 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007460 }
Willy Tarreau102df612014-05-07 23:56:38 +02007461 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7462 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7463 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007464 }
7465 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007466
7467 /* create the task associated with the proxy */
7468 curproxy->task = task_new();
7469 if (curproxy->task) {
7470 curproxy->task->context = curproxy;
7471 curproxy->task->process = manage_proxy;
7472 /* no need to queue, it will be done automatically if some
7473 * listener gets limited.
7474 */
7475 curproxy->task->expire = TICK_ETERNITY;
7476 } else {
7477 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7478 curproxy->id);
7479 cfgerr++;
7480 }
Willy Tarreaub369a042014-09-16 13:21:03 +02007481 }
7482
Willy Tarreaufbb78422011-06-05 15:38:35 +02007483 /* automatically compute fullconn if not set. We must not do it in the
7484 * loop above because cross-references are not yet fully resolved.
7485 */
7486 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7487 /* If <fullconn> is not set, let's set it to 10% of the sum of
7488 * the possible incoming frontend's maxconns.
7489 */
7490 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7491 struct proxy *fe;
7492 int total = 0;
7493
7494 /* sum up the number of maxconns of frontends which
7495 * reference this backend at least once or which are
7496 * the same one ('listen').
7497 */
7498 for (fe = proxy; fe; fe = fe->next) {
7499 struct switching_rule *rule;
7500 struct hdr_exp *exp;
7501 int found = 0;
7502
7503 if (!(fe->cap & PR_CAP_FE))
7504 continue;
7505
7506 if (fe == curproxy) /* we're on a "listen" instance */
7507 found = 1;
7508
7509 if (fe->defbe.be == curproxy) /* "default_backend" */
7510 found = 1;
7511
7512 /* check if a "use_backend" rule matches */
7513 if (!found) {
7514 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007515 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007516 found = 1;
7517 break;
7518 }
7519 }
7520 }
7521
7522 /* check if a "reqsetbe" rule matches */
7523 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7524 if (exp->action == ACT_SETBE &&
7525 (struct proxy *)exp->replace == curproxy) {
7526 found = 1;
7527 break;
7528 }
7529 }
7530
7531 /* now we've checked all possible ways to reference a backend
7532 * from a frontend.
7533 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007534 if (!found)
7535 continue;
7536 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007537 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007538 /* we have the sum of the maxconns in <total>. We only
7539 * keep 10% of that sum to set the default fullconn, with
7540 * a hard minimum of 1 (to avoid a divide by zero).
7541 */
7542 curproxy->fullconn = (total + 9) / 10;
7543 if (!curproxy->fullconn)
7544 curproxy->fullconn = 1;
7545 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007546 }
7547
Willy Tarreau056f5682010-06-06 15:51:11 +02007548 /* initialize stick-tables on backend capable proxies. This must not
7549 * be done earlier because the data size may be discovered while parsing
7550 * other proxies.
7551 */
Godbach9703e662013-12-11 21:11:41 +08007552 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007553 if (curproxy->state == PR_STSTOPPED)
7554 continue;
7555
Godbach9703e662013-12-11 21:11:41 +08007556 if (!stktable_init(&curproxy->table)) {
7557 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7558 cfgerr++;
7559 }
7560 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007561
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007562 /*
7563 * Recount currently required checks.
7564 */
7565
7566 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7567 int optnum;
7568
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007569 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7570 if (curproxy->options & cfg_opts[optnum].val)
7571 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007572
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007573 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7574 if (curproxy->options2 & cfg_opts2[optnum].val)
7575 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007576 }
7577
Willy Tarreau122541c2011-09-07 21:24:49 +02007578 if (peers) {
7579 struct peers *curpeers = peers, **last;
7580 struct peer *p, *pb;
7581
7582 /* Remove all peers sections which don't have a valid listener.
7583 * This can happen when a peers section is never referenced and
7584 * does not contain a local peer.
7585 */
7586 last = &peers;
7587 while (*last) {
7588 curpeers = *last;
7589 if (curpeers->peers_fe) {
7590 last = &curpeers->next;
7591 continue;
7592 }
7593
7594 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7595 curpeers->id, localpeer);
7596
7597 p = curpeers->remote;
7598 while (p) {
7599 pb = p->next;
7600 free(p->id);
7601 free(p);
7602 p = pb;
7603 }
7604
7605 /* Destroy and unlink this curpeers section.
7606 * Note: curpeers is backed up into *last.
7607 */
7608 free(curpeers->id);
7609 curpeers = curpeers->next;
7610 free(*last);
7611 *last = curpeers;
7612 }
7613 }
7614
Willy Tarreau34eb6712011-10-24 18:15:04 +02007615 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007616 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007617 MEM_F_SHARED);
7618
Willy Tarreaubb925012009-07-23 13:36:36 +02007619 if (cfgerr > 0)
7620 err_code |= ERR_ALERT | ERR_FATAL;
7621 out:
7622 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007623}
7624
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007625/*
7626 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7627 * parsing sessions.
7628 */
7629void cfg_register_keywords(struct cfg_kw_list *kwl)
7630{
7631 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7632}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007633
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007634/*
7635 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7636 */
7637void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7638{
7639 LIST_DEL(&kwl->list);
7640 LIST_INIT(&kwl->list);
7641}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007642
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007643/* this function register new section in the haproxy configuration file.
7644 * <section_name> is the name of this new section and <section_parser>
7645 * is the called parser. If two section declaration have the same name,
7646 * only the first declared is used.
7647 */
7648int cfg_register_section(char *section_name,
7649 int (*section_parser)(const char *, int, char **, int))
7650{
7651 struct cfg_section *cs;
7652
7653 cs = calloc(1, sizeof(*cs));
7654 if (!cs) {
7655 Alert("register section '%s': out of memory.\n", section_name);
7656 return 0;
7657 }
7658
7659 cs->section_name = section_name;
7660 cs->section_parser = section_parser;
7661
7662 LIST_ADDQ(&sections, &cs->list);
7663
7664 return 1;
7665}
7666
Willy Tarreaubaaee002006-06-26 02:48:02 +02007667/*
7668 * Local variables:
7669 * c-indent-level: 8
7670 * c-basic-offset: 8
7671 * End:
7672 */