blob: c5f20a36a29e5e726a4ee30e571e915e2f045fe8 [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 Tarreau33cb0652014-12-23 22:52:37 +0100699 else if (!strcmp(args[0], "tune.buffers.limit")) {
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.buf_limit = atol(args[1]);
706 if (global.tune.buf_limit) {
707 if (global.tune.buf_limit < 3)
708 global.tune.buf_limit = 3;
709 if (global.tune.buf_limit <= global.tune.reserved_bufs)
710 global.tune.buf_limit = global.tune.reserved_bufs + 1;
711 }
712 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100713 else if (!strcmp(args[0], "tune.buffers.reserve")) {
714 if (*(args[1]) == 0) {
715 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
716 err_code |= ERR_ALERT | ERR_FATAL;
717 goto out;
718 }
719 global.tune.reserved_bufs = atol(args[1]);
720 if (global.tune.reserved_bufs < 2)
721 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100722 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
723 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100724 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200725 else if (!strcmp(args[0], "tune.bufsize")) {
726 if (*(args[1]) == 0) {
727 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 global.tune.bufsize = atol(args[1]);
732 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
733 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100734 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100735 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200736 }
737 else if (!strcmp(args[0], "tune.maxrewrite")) {
738 if (*(args[1]) == 0) {
739 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743 global.tune.maxrewrite = atol(args[1]);
744 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
745 global.tune.maxrewrite = global.tune.bufsize / 2;
746 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100747 else if (!strcmp(args[0], "tune.idletimer")) {
748 unsigned int idle;
749 const char *res;
750
751 if (*(args[1]) == 0) {
752 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756
757 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
758 if (res) {
759 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
760 file, linenum, *res, args[0]);
761 err_code |= ERR_ALERT | ERR_FATAL;
762 goto out;
763 }
764
765 if (idle > 65535) {
766 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
769 }
770 global.tune.idle_timer = idle;
771 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100772 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
773 if (global.tune.client_rcvbuf != 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_rcvbuf = atol(args[1]);
784 }
785 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
786 if (global.tune.server_rcvbuf != 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_rcvbuf = atol(args[1]);
797 }
798 else if (!strcmp(args[0], "tune.sndbuf.client")) {
799 if (global.tune.client_sndbuf != 0) {
800 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
801 err_code |= ERR_ALERT;
802 goto out;
803 }
804 if (*(args[1]) == 0) {
805 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
806 err_code |= ERR_ALERT | ERR_FATAL;
807 goto out;
808 }
809 global.tune.client_sndbuf = atol(args[1]);
810 }
811 else if (!strcmp(args[0], "tune.sndbuf.server")) {
812 if (global.tune.server_sndbuf != 0) {
813 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
814 err_code |= ERR_ALERT;
815 goto out;
816 }
817 if (*(args[1]) == 0) {
818 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
819 err_code |= ERR_ALERT | ERR_FATAL;
820 goto out;
821 }
822 global.tune.server_sndbuf = atol(args[1]);
823 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200824 else if (!strcmp(args[0], "tune.pipesize")) {
825 if (*(args[1]) == 0) {
826 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
827 err_code |= ERR_ALERT | ERR_FATAL;
828 goto out;
829 }
830 global.tune.pipesize = atol(args[1]);
831 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100832 else if (!strcmp(args[0], "tune.http.cookielen")) {
833 if (*(args[1]) == 0) {
834 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
835 err_code |= ERR_ALERT | ERR_FATAL;
836 goto out;
837 }
838 global.tune.cookie_len = atol(args[1]) + 1;
839 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200840 else if (!strcmp(args[0], "tune.http.maxhdr")) {
841 if (*(args[1]) == 0) {
842 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
843 err_code |= ERR_ALERT | ERR_FATAL;
844 goto out;
845 }
846 global.tune.max_http_hdr = atol(args[1]);
847 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100848 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
849#ifdef USE_ZLIB
850 if (*args[1]) {
851 global.tune.zlibmemlevel = atoi(args[1]);
852 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
853 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
854 file, linenum, args[0]);
855 err_code |= ERR_ALERT | ERR_FATAL;
856 goto out;
857 }
858 } else {
859 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
860 file, linenum, args[0]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863 }
864#else
865 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
866 err_code |= ERR_ALERT | ERR_FATAL;
867 goto out;
868#endif
869 }
870 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
871#ifdef USE_ZLIB
872 if (*args[1]) {
873 global.tune.zlibwindowsize = atoi(args[1]);
874 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
875 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
876 file, linenum, args[0]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880 } else {
881 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
882 file, linenum, args[0]);
883 err_code |= ERR_ALERT | ERR_FATAL;
884 goto out;
885 }
886#else
887 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
888 err_code |= ERR_ALERT | ERR_FATAL;
889 goto out;
890#endif
891 }
William Lallemandf3747832012-11-09 12:33:10 +0100892 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
893 if (*args[1]) {
894 global.tune.comp_maxlevel = atoi(args[1]);
895 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
896 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
897 file, linenum, args[0]);
898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
900 }
901 } else {
902 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
903 file, linenum, args[0]);
904 err_code |= ERR_ALERT | ERR_FATAL;
905 goto out;
906 }
907 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908 else if (!strcmp(args[0], "uid")) {
909 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200910 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200911 err_code |= ERR_ALERT;
912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200913 }
914 if (*(args[1]) == 0) {
915 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 }
919 global.uid = atol(args[1]);
920 }
921 else if (!strcmp(args[0], "gid")) {
922 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200923 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200924 err_code |= ERR_ALERT;
925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 }
927 if (*(args[1]) == 0) {
928 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200929 err_code |= ERR_ALERT | ERR_FATAL;
930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200931 }
932 global.gid = atol(args[1]);
933 }
Simon Horman98637e52014-06-20 12:30:16 +0900934 else if (!strcmp(args[0], "external-check")) {
935 global.external_check = 1;
936 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200937 /* user/group name handling */
938 else if (!strcmp(args[0], "user")) {
939 struct passwd *ha_user;
940 if (global.uid != 0) {
941 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200942 err_code |= ERR_ALERT;
943 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200944 }
945 errno = 0;
946 ha_user = getpwnam(args[1]);
947 if (ha_user != NULL) {
948 global.uid = (int)ha_user->pw_uid;
949 }
950 else {
951 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 +0200952 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200953 }
954 }
955 else if (!strcmp(args[0], "group")) {
956 struct group *ha_group;
957 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200958 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200959 err_code |= ERR_ALERT;
960 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200961 }
962 errno = 0;
963 ha_group = getgrnam(args[1]);
964 if (ha_group != NULL) {
965 global.gid = (int)ha_group->gr_gid;
966 }
967 else {
968 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 +0200969 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200970 }
971 }
972 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200974 if (*(args[1]) == 0) {
975 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200976 err_code |= ERR_ALERT | ERR_FATAL;
977 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200978 }
979 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100980 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
981 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
982 file, linenum, args[0], LONGBITS, global.nbproc);
983 err_code |= ERR_ALERT | ERR_FATAL;
984 goto out;
985 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200986 }
987 else if (!strcmp(args[0], "maxconn")) {
988 if (global.maxconn != 0) {
989 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200990 err_code |= ERR_ALERT;
991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 }
993 if (*(args[1]) == 0) {
994 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200995 err_code |= ERR_ALERT | ERR_FATAL;
996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997 }
998 global.maxconn = atol(args[1]);
999#ifdef SYSTEM_MAXCONN
1000 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1001 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);
1002 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001003 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001004 }
1005#endif /* SYSTEM_MAXCONN */
1006 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001007 else if (!strcmp(args[0], "maxsslconn")) {
1008#ifdef USE_OPENSSL
1009 if (*(args[1]) == 0) {
1010 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1011 err_code |= ERR_ALERT | ERR_FATAL;
1012 goto out;
1013 }
1014 global.maxsslconn = atol(args[1]);
1015#else
Emeric Brun0914df82012-10-02 18:45:42 +02001016 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1017 err_code |= ERR_ALERT | ERR_FATAL;
1018 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001019#endif
1020 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001021 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1022#ifdef USE_OPENSSL
1023 if (*(args[1]) == 0) {
1024 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1025 err_code |= ERR_ALERT | ERR_FATAL;
1026 goto out;
1027 }
1028 free(global.listen_default_ciphers);
1029 global.listen_default_ciphers = strdup(args[1]);
1030#else
1031 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1032 err_code |= ERR_ALERT | ERR_FATAL;
1033 goto out;
1034#endif
1035 }
1036 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1037#ifdef USE_OPENSSL
1038 if (*(args[1]) == 0) {
1039 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1040 err_code |= ERR_ALERT | ERR_FATAL;
1041 goto out;
1042 }
1043 free(global.connect_default_ciphers);
1044 global.connect_default_ciphers = strdup(args[1]);
1045#else
1046 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
1049#endif
1050 }
Emeric Brun850efd52014-01-29 12:24:34 +01001051 else if (!strcmp(args[0], "ssl-server-verify")) {
1052 if (*(args[1]) == 0) {
1053 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1054 err_code |= ERR_ALERT | ERR_FATAL;
1055 goto out;
1056 }
1057 if (strcmp(args[1],"none") == 0)
1058 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1059 else if (strcmp(args[1],"required") == 0)
1060 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1061 else {
1062 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1063 err_code |= ERR_ALERT | ERR_FATAL;
1064 goto out;
1065 }
1066 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001067 else if (!strcmp(args[0], "maxconnrate")) {
1068 if (global.cps_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.cps_lim = atol(args[1]);
1079 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001080 else if (!strcmp(args[0], "maxsessrate")) {
1081 if (global.sps_lim != 0) {
1082 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1083 err_code |= ERR_ALERT;
1084 goto out;
1085 }
1086 if (*(args[1]) == 0) {
1087 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1088 err_code |= ERR_ALERT | ERR_FATAL;
1089 goto out;
1090 }
1091 global.sps_lim = atol(args[1]);
1092 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001093 else if (!strcmp(args[0], "maxsslrate")) {
1094 if (global.ssl_lim != 0) {
1095 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1096 err_code |= ERR_ALERT;
1097 goto out;
1098 }
1099 if (*(args[1]) == 0) {
1100 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1101 err_code |= ERR_ALERT | ERR_FATAL;
1102 goto out;
1103 }
1104 global.ssl_lim = atol(args[1]);
1105 }
William Lallemandd85f9172012-11-09 17:05:39 +01001106 else if (!strcmp(args[0], "maxcomprate")) {
1107 if (*(args[1]) == 0) {
1108 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto out;
1111 }
1112 global.comp_rate_lim = atoi(args[1]) * 1024;
1113 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001114 else if (!strcmp(args[0], "maxpipes")) {
1115 if (global.maxpipes != 0) {
1116 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001117 err_code |= ERR_ALERT;
1118 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001119 }
1120 if (*(args[1]) == 0) {
1121 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001122 err_code |= ERR_ALERT | ERR_FATAL;
1123 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001124 }
1125 global.maxpipes = atol(args[1]);
1126 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001127 else if (!strcmp(args[0], "maxzlibmem")) {
1128 if (*(args[1]) == 0) {
1129 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1130 err_code |= ERR_ALERT | ERR_FATAL;
1131 goto out;
1132 }
William Lallemande3a7d992012-11-20 11:25:20 +01001133 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001134 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001135 else if (!strcmp(args[0], "maxcompcpuusage")) {
1136 if (*(args[1]) == 0) {
1137 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1138 err_code |= ERR_ALERT | ERR_FATAL;
1139 goto out;
1140 }
1141 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001142 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001143 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1144 err_code |= ERR_ALERT | ERR_FATAL;
1145 goto out;
1146 }
1147}
1148
Willy Tarreaubaaee002006-06-26 02:48:02 +02001149 else if (!strcmp(args[0], "ulimit-n")) {
1150 if (global.rlimit_nofile != 0) {
1151 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001152 err_code |= ERR_ALERT;
1153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154 }
1155 if (*(args[1]) == 0) {
1156 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001157 err_code |= ERR_ALERT | ERR_FATAL;
1158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001159 }
1160 global.rlimit_nofile = atol(args[1]);
1161 }
1162 else if (!strcmp(args[0], "chroot")) {
1163 if (global.chroot != NULL) {
1164 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001165 err_code |= ERR_ALERT;
1166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001167 }
1168 if (*(args[1]) == 0) {
1169 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001170 err_code |= ERR_ALERT | ERR_FATAL;
1171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001172 }
1173 global.chroot = strdup(args[1]);
1174 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001175 else if (!strcmp(args[0], "description")) {
1176 int i, len=0;
1177 char *d;
1178
1179 if (!*args[1]) {
1180 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1181 file, linenum, args[0]);
1182 err_code |= ERR_ALERT | ERR_FATAL;
1183 goto out;
1184 }
1185
Willy Tarreau348acfe2014-04-14 15:00:39 +02001186 for (i = 1; *args[i]; i++)
1187 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001188
1189 if (global.desc)
1190 free(global.desc);
1191
1192 global.desc = d = (char *)calloc(1, len);
1193
Willy Tarreau348acfe2014-04-14 15:00:39 +02001194 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1195 for (i = 2; *args[i]; i++)
1196 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001197 }
1198 else if (!strcmp(args[0], "node")) {
1199 int i;
1200 char c;
1201
1202 for (i=0; args[1][i]; i++) {
1203 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001204 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1205 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001206 break;
1207 }
1208
1209 if (!i || args[1][i]) {
1210 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1211 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1212 file, linenum, args[0]);
1213 err_code |= ERR_ALERT | ERR_FATAL;
1214 goto out;
1215 }
1216
1217 if (global.node)
1218 free(global.node);
1219
1220 global.node = strdup(args[1]);
1221 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001222 else if (!strcmp(args[0], "pidfile")) {
1223 if (global.pidfile != NULL) {
1224 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001225 err_code |= ERR_ALERT;
1226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001227 }
1228 if (*(args[1]) == 0) {
1229 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001230 err_code |= ERR_ALERT | ERR_FATAL;
1231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001232 }
1233 global.pidfile = strdup(args[1]);
1234 }
Emeric Bruned760922010-10-22 17:59:25 +02001235 else if (!strcmp(args[0], "unix-bind")) {
1236 int cur_arg = 1;
1237 while (*(args[cur_arg])) {
1238 if (!strcmp(args[cur_arg], "prefix")) {
1239 if (global.unix_bind.prefix != NULL) {
1240 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1241 err_code |= ERR_ALERT;
1242 cur_arg += 2;
1243 continue;
1244 }
1245
1246 if (*(args[cur_arg+1]) == 0) {
1247 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1248 err_code |= ERR_ALERT | ERR_FATAL;
1249 goto out;
1250 }
1251 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1252 cur_arg += 2;
1253 continue;
1254 }
1255
1256 if (!strcmp(args[cur_arg], "mode")) {
1257
1258 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1259 cur_arg += 2;
1260 continue;
1261 }
1262
1263 if (!strcmp(args[cur_arg], "uid")) {
1264
1265 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1266 cur_arg += 2;
1267 continue;
1268 }
1269
1270 if (!strcmp(args[cur_arg], "gid")) {
1271
1272 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1273 cur_arg += 2;
1274 continue;
1275 }
1276
1277 if (!strcmp(args[cur_arg], "user")) {
1278 struct passwd *user;
1279
1280 user = getpwnam(args[cur_arg + 1]);
1281 if (!user) {
1282 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1283 file, linenum, args[0], args[cur_arg + 1 ]);
1284 err_code |= ERR_ALERT | ERR_FATAL;
1285 goto out;
1286 }
1287
1288 global.unix_bind.ux.uid = user->pw_uid;
1289 cur_arg += 2;
1290 continue;
1291 }
1292
1293 if (!strcmp(args[cur_arg], "group")) {
1294 struct group *group;
1295
1296 group = getgrnam(args[cur_arg + 1]);
1297 if (!group) {
1298 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1299 file, linenum, args[0], args[cur_arg + 1 ]);
1300 err_code |= ERR_ALERT | ERR_FATAL;
1301 goto out;
1302 }
1303
1304 global.unix_bind.ux.gid = group->gr_gid;
1305 cur_arg += 2;
1306 continue;
1307 }
1308
Willy Tarreaub48f9582011-09-05 01:17:06 +02001309 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001310 file, linenum, args[0]);
1311 err_code |= ERR_ALERT | ERR_FATAL;
1312 goto out;
1313 }
1314 }
William Lallemand0f99e342011-10-12 17:50:54 +02001315 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1316 /* delete previous herited or defined syslog servers */
1317 struct logsrv *back;
1318 struct logsrv *tmp;
1319
1320 if (*(args[1]) != 0) {
1321 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1322 err_code |= ERR_ALERT | ERR_FATAL;
1323 goto out;
1324 }
1325
1326 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1327 LIST_DEL(&tmp->list);
1328 free(tmp);
1329 }
1330 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001331 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001332 struct sockaddr_storage *sk;
1333 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001334 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001335 int arg = 0;
1336 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001337
Willy Tarreaubaaee002006-06-26 02:48:02 +02001338 if (*(args[1]) == 0 || *(args[2]) == 0) {
1339 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001340 err_code |= ERR_ALERT | ERR_FATAL;
1341 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001342 }
William Lallemand0f99e342011-10-12 17:50:54 +02001343
1344 logsrv = calloc(1, sizeof(struct logsrv));
1345
Willy Tarreau18324f52014-06-27 18:10:07 +02001346 /* just after the address, a length may be specified */
1347 if (strcmp(args[arg+2], "len") == 0) {
1348 len = atoi(args[arg+3]);
1349 if (len < 80 || len > 65535) {
1350 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1351 file, linenum, args[arg+3]);
1352 err_code |= ERR_ALERT | ERR_FATAL;
1353 goto out;
1354 }
1355 logsrv->maxlen = len;
1356
1357 /* skip these two args */
1358 arg += 2;
1359 }
1360 else
1361 logsrv->maxlen = MAX_SYSLOG_LEN;
1362
1363 if (logsrv->maxlen > global.max_syslog_len) {
1364 global.max_syslog_len = logsrv->maxlen;
1365 logline = realloc(logline, global.max_syslog_len + 1);
1366 }
1367
1368 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001369 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001370 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001371 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001372 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001373 }
1374
William Lallemand0f99e342011-10-12 17:50:54 +02001375 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001376 if (*(args[arg+3])) {
1377 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001378 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001379 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001380 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001381 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001382 }
1383 }
1384
William Lallemand0f99e342011-10-12 17:50:54 +02001385 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001386 if (*(args[arg+4])) {
1387 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001388 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001389 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001390 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001391 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001392 }
1393 }
1394
Willy Tarreau902636f2013-03-10 19:44:48 +01001395 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001396 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001397 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001398 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001399 free(logsrv);
1400 goto out;
1401 }
1402 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001403
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001404 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001405 if (port1 != port2) {
1406 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1407 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001408 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001409 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001410 goto out;
1411 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001412
William Lallemand0f99e342011-10-12 17:50:54 +02001413 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001414 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001415 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001416 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001417
William Lallemand0f99e342011-10-12 17:50:54 +02001418 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001419 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001420 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1421 char *name;
1422 int len;
1423
1424 if (global.log_send_hostname != NULL) {
1425 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1426 err_code |= ERR_ALERT;
1427 goto out;
1428 }
1429
1430 if (*(args[1]))
1431 name = args[1];
1432 else
1433 name = hostname;
1434
1435 len = strlen(name);
1436
1437 /* We'll add a space after the name to respect the log format */
1438 free(global.log_send_hostname);
1439 global.log_send_hostname = malloc(len + 2);
1440 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1441 }
Kevinm48936af2010-12-22 16:08:21 +00001442 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1443 if (*(args[1]) == 0) {
1444 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1445 err_code |= ERR_ALERT | ERR_FATAL;
1446 goto out;
1447 }
1448 free(global.log_tag);
1449 global.log_tag = strdup(args[1]);
1450 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001451 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1452 if (global.spread_checks != 0) {
1453 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001454 err_code |= ERR_ALERT;
1455 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001456 }
1457 if (*(args[1]) == 0) {
1458 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001459 err_code |= ERR_ALERT | ERR_FATAL;
1460 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001461 }
1462 global.spread_checks = atol(args[1]);
1463 if (global.spread_checks < 0 || global.spread_checks > 50) {
1464 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001465 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001466 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001468 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1469 const char *err;
1470 unsigned int val;
1471
1472
1473 if (*(args[1]) == 0) {
1474 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1475 err_code |= ERR_ALERT | ERR_FATAL;
1476 goto out;
1477 }
1478
1479 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1480 if (err) {
1481 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1482 err_code |= ERR_ALERT | ERR_FATAL;
1483 }
1484 global.max_spread_checks = val;
1485 if (global.max_spread_checks < 0) {
1486 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1487 err_code |= ERR_ALERT | ERR_FATAL;
1488 }
1489 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001490 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1491#ifdef USE_CPU_AFFINITY
1492 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001493 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001494 unsigned long cpus = 0;
1495
1496 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001497 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001498 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001499 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001500 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001501 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001502 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001503 proc = atol(args[1]);
1504 if (proc >= 1 && proc <= LONGBITS)
1505 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001506 }
1507
1508 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001509 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",
1510 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001511 err_code |= ERR_ALERT | ERR_FATAL;
1512 goto out;
1513 }
1514
1515 cur_arg = 2;
1516 while (*args[cur_arg]) {
1517 unsigned int low, high;
1518
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001519 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001520 char *dash = strchr(args[cur_arg], '-');
1521
1522 low = high = str2uic(args[cur_arg]);
1523 if (dash)
1524 high = str2uic(dash + 1);
1525
1526 if (high < low) {
1527 unsigned int swap = low;
1528 low = high;
1529 high = swap;
1530 }
1531
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001532 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001533 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001534 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001535 err_code |= ERR_ALERT | ERR_FATAL;
1536 goto out;
1537 }
1538
1539 while (low <= high)
1540 cpus |= 1UL << low++;
1541 }
1542 else {
1543 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1544 file, linenum, args[0], args[cur_arg]);
1545 err_code |= ERR_ALERT | ERR_FATAL;
1546 goto out;
1547 }
1548 cur_arg++;
1549 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001550 for (i = 0; i < LONGBITS; i++)
1551 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001552 global.cpu_map[i] = cpus;
1553#else
1554 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1555 err_code |= ERR_ALERT | ERR_FATAL;
1556 goto out;
1557#endif
1558 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001560 struct cfg_kw_list *kwl;
1561 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001562 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001563
1564 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1565 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1566 if (kwl->kw[index].section != CFG_GLOBAL)
1567 continue;
1568 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001569 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001570 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001571 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001572 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001573 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001574 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001575 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001576 err_code |= ERR_WARN;
1577 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001578 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001579 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001580 }
1581 }
1582 }
1583
Willy Tarreaubaaee002006-06-26 02:48:02 +02001584 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001585 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001587
Willy Tarreau058e9072009-07-20 09:30:05 +02001588 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001589 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001590 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591}
1592
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001593void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001594{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001595 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596 defproxy.mode = PR_MODE_TCP;
1597 defproxy.state = PR_STNEW;
1598 defproxy.maxconn = cfg_maxpconn;
1599 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001600
Simon Horman66183002013-02-23 10:16:43 +09001601 defproxy.defsrv.check.inter = DEF_CHKINTR;
1602 defproxy.defsrv.check.fastinter = 0;
1603 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001604 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1605 defproxy.defsrv.agent.fastinter = 0;
1606 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001607 defproxy.defsrv.check.rise = DEF_RISETIME;
1608 defproxy.defsrv.check.fall = DEF_FALLTIME;
1609 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1610 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001611 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001612 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001613 defproxy.defsrv.maxqueue = 0;
1614 defproxy.defsrv.minconn = 0;
1615 defproxy.defsrv.maxconn = 0;
1616 defproxy.defsrv.slowstart = 0;
1617 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1618 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1619 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620}
1621
Willy Tarreauade5ec42010-01-28 19:33:49 +01001622
Willy Tarreau63af98d2014-05-18 08:11:41 +02001623/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1624 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1625 * ERR_FATAL in case of error.
1626 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001627static int create_cond_regex_rule(const char *file, int line,
1628 struct proxy *px, int dir, int action, int flags,
1629 const char *cmd, const char *reg, const char *repl,
1630 const char **cond_start)
1631{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001632 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001633 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001634 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001635 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001636 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001637 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001638 int cs;
1639 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001640
1641 if (px == &defproxy) {
1642 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001643 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001644 goto err;
1645 }
1646
1647 if (*reg == 0) {
1648 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001649 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001650 goto err;
1651 }
1652
1653 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001654 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001655
Willy Tarreau5321c422010-01-28 20:35:13 +01001656 if (cond_start &&
1657 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001658 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1659 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1660 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001661 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001662 goto err;
1663 }
1664 }
1665 else if (cond_start && **cond_start) {
1666 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1667 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001668 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001669 goto err;
1670 }
1671
Willy Tarreau63af98d2014-05-18 08:11:41 +02001672 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001673 (dir == SMP_OPT_DIR_REQ) ?
1674 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1675 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1676 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001677
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001678 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001679 if (!preg) {
1680 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001681 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001682 goto err;
1683 }
1684
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001685 cs = !(flags & REG_ICASE);
1686 cap = !(flags & REG_NOSUB);
1687 error = NULL;
1688 if (!regex_comp(reg, preg, cs, cap, &error)) {
1689 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1690 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001691 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001692 goto err;
1693 }
1694
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001695 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001696 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001697 if (repl && err) {
1698 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1699 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001700 ret_code |= ERR_ALERT | ERR_FATAL;
1701 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001702 }
1703
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001704 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001705 ret_code |= ERR_WARN;
1706
1707 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001708
Willy Tarreau63af98d2014-05-18 08:11:41 +02001709 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001710 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001711 err:
1712 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001713 free(errmsg);
1714 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001715}
1716
Willy Tarreaubaaee002006-06-26 02:48:02 +02001717/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001718 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001719 * Returns the error code, 0 if OK, or any combination of :
1720 * - ERR_ABORT: must abort ASAP
1721 * - ERR_FATAL: we can continue parsing but not start the service
1722 * - ERR_WARN: a warning has been emitted
1723 * - ERR_ALERT: an alert has been emitted
1724 * Only the two first ones can stop processing, the two others are just
1725 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001726 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001727int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1728{
1729 static struct peers *curpeers = NULL;
1730 struct peer *newpeer = NULL;
1731 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001732 struct bind_conf *bind_conf;
1733 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001734 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001735 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001736
1737 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001738 if (!*args[1]) {
1739 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001740 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001741 goto out;
1742 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001743
1744 err = invalid_char(args[1]);
1745 if (err) {
1746 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1747 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001748 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001749 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001750 }
1751
1752 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1753 /*
1754 * If there are two proxies with the same name only following
1755 * combinations are allowed:
1756 */
1757 if (strcmp(curpeers->id, args[1]) == 0) {
1758 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1759 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1760 err_code |= ERR_WARN;
1761 }
1762 }
1763
1764 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1765 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1766 err_code |= ERR_ALERT | ERR_ABORT;
1767 goto out;
1768 }
1769
1770 curpeers->next = peers;
1771 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001772 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001773 curpeers->conf.line = linenum;
1774 curpeers->last_change = now.tv_sec;
1775 curpeers->id = strdup(args[1]);
1776 }
1777 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001778 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001779 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001780 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001781
1782 if (!*args[2]) {
1783 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1784 file, linenum, args[0]);
1785 err_code |= ERR_ALERT | ERR_FATAL;
1786 goto out;
1787 }
1788
1789 err = invalid_char(args[1]);
1790 if (err) {
1791 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1792 file, linenum, *err, args[1]);
1793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
1795 }
1796
1797 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1798 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1799 err_code |= ERR_ALERT | ERR_ABORT;
1800 goto out;
1801 }
1802
1803 /* the peers are linked backwards first */
1804 curpeers->count++;
1805 newpeer->next = curpeers->remote;
1806 curpeers->remote = newpeer;
1807 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001808 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001809 newpeer->conf.line = linenum;
1810
1811 newpeer->last_change = now.tv_sec;
1812 newpeer->id = strdup(args[1]);
1813
Willy Tarreau902636f2013-03-10 19:44:48 +01001814 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001815 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001816 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001817 err_code |= ERR_ALERT | ERR_FATAL;
1818 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001819 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001820
1821 proto = protocol_by_family(sk->ss_family);
1822 if (!proto || !proto->connect) {
1823 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1824 file, linenum, args[0], args[1]);
1825 err_code |= ERR_ALERT | ERR_FATAL;
1826 goto out;
1827 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001828
1829 if (port1 != port2) {
1830 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1831 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001832 err_code |= ERR_ALERT | ERR_FATAL;
1833 goto out;
1834 }
1835
Willy Tarreau2aa38802013-02-20 19:20:59 +01001836 if (!port1) {
1837 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1838 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001839 err_code |= ERR_ALERT | ERR_FATAL;
1840 goto out;
1841 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001842
Emeric Brun32da3c42010-09-23 18:39:19 +02001843 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001844 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001845 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001846 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001847
Emeric Brun32da3c42010-09-23 18:39:19 +02001848 if (strcmp(newpeer->id, localpeer) == 0) {
1849 /* Current is local peer, it define a frontend */
1850 newpeer->local = 1;
1851
1852 if (!curpeers->peers_fe) {
1853 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1854 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1855 err_code |= ERR_ALERT | ERR_ABORT;
1856 goto out;
1857 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001858
Willy Tarreau237250c2011-07-29 01:49:03 +02001859 init_new_proxy(curpeers->peers_fe);
1860 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001861
1862 curpeers->peers_fe->last_change = now.tv_sec;
1863 curpeers->peers_fe->id = strdup(args[1]);
1864 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001865 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001866 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1867 curpeers->peers_fe->timeout.connect = 5000;
1868 curpeers->peers_fe->accept = peer_accept;
1869 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001870 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1871 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001872
1873 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1874
Willy Tarreau902636f2013-03-10 19:44:48 +01001875 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1876 if (errmsg && *errmsg) {
1877 indent_msg(&errmsg, 2);
1878 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001879 }
1880 else
1881 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1882 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001883 err_code |= ERR_FATAL;
1884 goto out;
1885 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001886
1887 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001888 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001889 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1890 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1891 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1892 l->accept = session_accept;
1893 l->handler = process_session;
1894 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1895 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1896 global.maxsock += l->maxconn;
1897 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001898 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001899 else {
1900 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1901 file, linenum, args[0], args[1],
1902 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1903 err_code |= ERR_FATAL;
1904 goto out;
1905 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001906 }
1907 } /* neither "peer" nor "peers" */
1908 else if (*args[0] != 0) {
1909 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1910 err_code |= ERR_ALERT | ERR_FATAL;
1911 goto out;
1912 }
1913
1914out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001915 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001916 return err_code;
1917}
1918
Willy Tarreau3842f002009-06-14 11:39:52 +02001919int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920{
1921 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001922 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001923 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001924 int rc;
1925 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001926 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001927 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001928 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001929 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001930 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931
Willy Tarreau977b8e42006-12-29 14:19:17 +01001932 if (!strcmp(args[0], "listen"))
1933 rc = PR_CAP_LISTEN;
1934 else if (!strcmp(args[0], "frontend"))
1935 rc = PR_CAP_FE | PR_CAP_RS;
1936 else if (!strcmp(args[0], "backend"))
1937 rc = PR_CAP_BE | PR_CAP_RS;
1938 else if (!strcmp(args[0], "ruleset"))
1939 rc = PR_CAP_RS;
1940 else
1941 rc = PR_CAP_NONE;
1942
1943 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001944 struct ebpt_node *node;
1945
Willy Tarreaubaaee002006-06-26 02:48:02 +02001946 if (!*args[1]) {
1947 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1948 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1949 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001950 err_code |= ERR_ALERT | ERR_ABORT;
1951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001952 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001953
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001954 err = invalid_char(args[1]);
1955 if (err) {
1956 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1957 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001958 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001959 }
1960
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001961 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1962 curproxy = container_of(node, struct proxy, conf.by_name);
1963
1964 if (strcmp(curproxy->id, args[1]) != 0)
1965 break;
1966
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001967 /*
1968 * If there are two proxies with the same name only following
1969 * combinations are allowed:
1970 *
1971 * listen backend frontend ruleset
1972 * listen - - - -
1973 * backend - - OK -
1974 * frontend - OK - -
1975 * ruleset - - - -
1976 */
1977
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001978 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1979 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001980 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1981 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1982 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001983 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001984 }
1985 }
1986
Willy Tarreaubaaee002006-06-26 02:48:02 +02001987 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1988 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001989 err_code |= ERR_ALERT | ERR_ABORT;
1990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001991 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001992
Willy Tarreau97cb7802010-01-03 20:23:58 +01001993 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001994 curproxy->next = proxy;
1995 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001996 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1997 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001998 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001999 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002000 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002001 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002002
2003 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002004 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002005 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02002006
Willy Tarreau4348fad2012-09-20 16:48:07 +02002007 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2008
Willy Tarreau902636f2013-03-10 19:44:48 +01002009 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2010 if (errmsg && *errmsg) {
2011 indent_msg(&errmsg, 2);
2012 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002013 }
2014 else
2015 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2016 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002017 err_code |= ERR_FATAL;
2018 goto out;
2019 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002020
Willy Tarreau4348fad2012-09-20 16:48:07 +02002021 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002022 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002023 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002024 }
2025
2026 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002027 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002028 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002029
Willy Tarreaubaaee002006-06-26 02:48:02 +02002030 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002032 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002033 curproxy->no_options = defproxy.no_options;
2034 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002035 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002036 curproxy->except_net = defproxy.except_net;
2037 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002038 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002039 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002040
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002041 if (defproxy.fwdfor_hdr_len) {
2042 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2043 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2044 }
2045
Willy Tarreaub86db342009-11-30 11:50:16 +01002046 if (defproxy.orgto_hdr_len) {
2047 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2048 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2049 }
2050
Mark Lamourinec2247f02012-01-04 13:02:01 -05002051 if (defproxy.server_id_hdr_len) {
2052 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2053 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2054 }
2055
Willy Tarreau977b8e42006-12-29 14:19:17 +01002056 if (curproxy->cap & PR_CAP_FE) {
2057 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002058 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002059 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002060
2061 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002062 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2063 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002064
2065 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2066 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002067
Willy Tarreau977b8e42006-12-29 14:19:17 +01002068 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002069 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002070 curproxy->fullconn = defproxy.fullconn;
2071 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002072 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002073
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002074 if (defproxy.check_req) {
2075 curproxy->check_req = calloc(1, defproxy.check_len);
2076 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2077 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002078 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002079
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002080 if (defproxy.expect_str) {
2081 curproxy->expect_str = strdup(defproxy.expect_str);
2082 if (defproxy.expect_regex) {
2083 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002084 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2085 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002086 }
2087 }
2088
Willy Tarreau67402132012-05-31 20:40:20 +02002089 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002090 if (defproxy.cookie_name)
2091 curproxy->cookie_name = strdup(defproxy.cookie_name);
2092 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002093 if (defproxy.cookie_domain)
2094 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002095
Willy Tarreau31936852010-10-06 16:59:56 +02002096 if (defproxy.cookie_maxidle)
2097 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2098
2099 if (defproxy.cookie_maxlife)
2100 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2101
Emeric Brun647caf12009-06-30 17:57:00 +02002102 if (defproxy.rdp_cookie_name)
2103 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2104 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2105
Willy Tarreau01732802007-11-01 22:48:15 +01002106 if (defproxy.url_param_name)
2107 curproxy->url_param_name = strdup(defproxy.url_param_name);
2108 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002109
Benoitaffb4812009-03-25 13:02:10 +01002110 if (defproxy.hh_name)
2111 curproxy->hh_name = strdup(defproxy.hh_name);
2112 curproxy->hh_len = defproxy.hh_len;
2113 curproxy->hh_match_domain = defproxy.hh_match_domain;
2114
Willy Tarreauef9a3602012-12-08 22:29:20 +01002115 if (defproxy.conn_src.iface_name)
2116 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2117 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002118 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002119#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002120 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002121#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002122 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002123
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002124 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002125 if (defproxy.capture_name)
2126 curproxy->capture_name = strdup(defproxy.capture_name);
2127 curproxy->capture_namelen = defproxy.capture_namelen;
2128 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002129 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002130
Willy Tarreau977b8e42006-12-29 14:19:17 +01002131 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002132 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002133 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002134 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002135 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002136 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002137 curproxy->mon_net = defproxy.mon_net;
2138 curproxy->mon_mask = defproxy.mon_mask;
2139 if (defproxy.monitor_uri)
2140 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2141 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002142 if (defproxy.defbe.name)
2143 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002144
2145 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002146 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2147 if (curproxy->conf.logformat_string &&
2148 curproxy->conf.logformat_string != default_http_log_format &&
2149 curproxy->conf.logformat_string != default_tcp_log_format &&
2150 curproxy->conf.logformat_string != clf_http_log_format)
2151 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2152
2153 if (defproxy.conf.lfs_file) {
2154 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2155 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2156 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002157 }
2158
2159 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002160 curproxy->timeout.connect = defproxy.timeout.connect;
2161 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002162 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002163 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002164 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002165 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002166 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002167 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002168 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002169 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002170 }
2171
Willy Tarreaubaaee002006-06-26 02:48:02 +02002172 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002173 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002174
2175 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002176 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002177 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002178 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002179 LIST_INIT(&node->list);
2180 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2181 }
2182
Willy Tarreau62a61232013-04-12 18:13:46 +02002183 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2184 if (curproxy->conf.uniqueid_format_string)
2185 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2186
Willy Tarreau094af4e2015-01-07 15:03:42 +01002187 if (defproxy.log_tag)
2188 curproxy->log_tag = strdup(defproxy.log_tag);
2189
Willy Tarreau62a61232013-04-12 18:13:46 +02002190 if (defproxy.conf.uif_file) {
2191 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2192 curproxy->conf.uif_line = defproxy.conf.uif_line;
2193 }
William Lallemanda73203e2012-03-12 12:48:57 +01002194
2195 /* copy default header unique id */
2196 if (defproxy.header_unique_id)
2197 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2198
William Lallemand82fe75c2012-10-23 10:25:10 +02002199 /* default compression options */
2200 if (defproxy.comp != NULL) {
2201 curproxy->comp = calloc(1, sizeof(struct comp));
2202 curproxy->comp->algos = defproxy.comp->algos;
2203 curproxy->comp->types = defproxy.comp->types;
2204 }
2205
Willy Tarreaubaaee002006-06-26 02:48:02 +02002206 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002207 curproxy->conf.used_listener_id = EB_ROOT;
2208 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002209
Simon Horman98637e52014-06-20 12:30:16 +09002210 if (defproxy.check_path)
2211 curproxy->check_path = strdup(defproxy.check_path);
2212 if (defproxy.check_command)
2213 curproxy->check_command = strdup(defproxy.check_command);
2214
Willy Tarreau93893792009-07-23 13:19:11 +02002215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002216 }
2217 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2218 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002219 /* FIXME-20070101: we should do this too at the end of the
2220 * config parsing to free all default values.
2221 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002222 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002223 free(defproxy.check_command);
2224 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002225 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002226 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002227 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002228 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002229 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002230 free(defproxy.capture_name);
2231 free(defproxy.monitor_uri);
2232 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002233 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002234 free(defproxy.fwdfor_hdr_name);
2235 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002236 free(defproxy.orgto_hdr_name);
2237 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002238 free(defproxy.server_id_hdr_name);
2239 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002240 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002241 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002242 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002243 free(defproxy.expect_regex);
2244 defproxy.expect_regex = NULL;
2245 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002246
Willy Tarreau62a61232013-04-12 18:13:46 +02002247 if (defproxy.conf.logformat_string != default_http_log_format &&
2248 defproxy.conf.logformat_string != default_tcp_log_format &&
2249 defproxy.conf.logformat_string != clf_http_log_format)
2250 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002251
Willy Tarreau62a61232013-04-12 18:13:46 +02002252 free(defproxy.conf.uniqueid_format_string);
2253 free(defproxy.conf.lfs_file);
2254 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002255 free(defproxy.log_tag);
Willy Tarreau196729e2012-05-31 19:30:26 +02002256
Willy Tarreaua534fea2008-08-03 12:19:50 +02002257 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002258 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002259
Willy Tarreaubaaee002006-06-26 02:48:02 +02002260 /* we cannot free uri_auth because it might already be used */
2261 init_default_instance();
2262 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002263 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2264 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002265 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002267 }
2268 else if (curproxy == NULL) {
2269 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002272 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002273
2274 /* update the current file and line being parsed */
2275 curproxy->conf.args.file = curproxy->conf.file;
2276 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002277
2278 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002279 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2280 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2281 if (err_code & ERR_FATAL)
2282 goto out;
2283 }
2284 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002285 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002286 int cur_arg;
2287
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288 if (curproxy == &defproxy) {
2289 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002290 err_code |= ERR_ALERT | ERR_FATAL;
2291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002293 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002294 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295
Willy Tarreau24709282013-03-10 21:32:12 +01002296 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002297 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002299 err_code |= ERR_ALERT | ERR_FATAL;
2300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002301 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002302
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002303 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002304
2305 /* use default settings for unix sockets */
2306 bind_conf->ux.uid = global.unix_bind.ux.uid;
2307 bind_conf->ux.gid = global.unix_bind.ux.gid;
2308 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002309
2310 /* NOTE: the following line might create several listeners if there
2311 * are comma-separated IPs or port ranges. So all further processing
2312 * will have to be applied to all listeners created after last_listen.
2313 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002314 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2315 if (errmsg && *errmsg) {
2316 indent_msg(&errmsg, 2);
2317 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002318 }
2319 else
2320 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2321 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002322 err_code |= ERR_ALERT | ERR_FATAL;
2323 goto out;
2324 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002325
Willy Tarreau4348fad2012-09-20 16:48:07 +02002326 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2327 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002328 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002329 }
2330
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002331 cur_arg = 2;
2332 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002333 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002334 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002335 char *err;
2336
Willy Tarreau26982662012-09-12 23:17:10 +02002337 kw = bind_find_kw(args[cur_arg]);
2338 if (kw) {
2339 char *err = NULL;
2340 int code;
2341
2342 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002343 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2344 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002345 cur_arg += 1 + kw->skip ;
2346 err_code |= ERR_ALERT | ERR_FATAL;
2347 goto out;
2348 }
2349
Willy Tarreau4348fad2012-09-20 16:48:07 +02002350 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002351 err_code |= code;
2352
2353 if (code) {
2354 if (err && *err) {
2355 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002356 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002357 }
2358 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002359 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2360 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002361 if (code & ERR_FATAL) {
2362 free(err);
2363 cur_arg += 1 + kw->skip;
2364 goto out;
2365 }
2366 }
2367 free(err);
2368 cur_arg += 1 + kw->skip;
2369 continue;
2370 }
2371
Willy Tarreau8638f482012-09-18 18:01:17 +02002372 err = NULL;
2373 if (!bind_dumped) {
2374 bind_dump_kws(&err);
2375 indent_msg(&err, 4);
2376 bind_dumped = 1;
2377 }
2378
2379 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2380 file, linenum, args[0], args[1], args[cur_arg],
2381 err ? " Registered keywords :" : "", err ? err : "");
2382 free(err);
2383
Willy Tarreau93893792009-07-23 13:19:11 +02002384 err_code |= ERR_ALERT | ERR_FATAL;
2385 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002386 }
Willy Tarreau93893792009-07-23 13:19:11 +02002387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002388 }
2389 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002390 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2392 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002393 err_code |= ERR_ALERT | ERR_FATAL;
2394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002396 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002397 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002398
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 /* flush useless bits */
2400 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002403 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002404 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002405 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002406
Willy Tarreau1c47f852006-07-09 08:22:27 +02002407 if (!*args[1]) {
2408 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2409 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002410 err_code |= ERR_ALERT | ERR_FATAL;
2411 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002412 }
2413
Willy Tarreaua534fea2008-08-03 12:19:50 +02002414 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002415 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002416 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002417 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002418 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2419
Willy Tarreau93893792009-07-23 13:19:11 +02002420 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002421 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2423 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2424 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2425 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2426 else {
2427 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002430 }
2431 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002432 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002433 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002434
2435 if (curproxy == &defproxy) {
2436 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2437 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002438 err_code |= ERR_ALERT | ERR_FATAL;
2439 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002440 }
2441
2442 if (!*args[1]) {
2443 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2444 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002445 err_code |= ERR_ALERT | ERR_FATAL;
2446 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002447 }
2448
2449 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002450 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002451
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002452 if (curproxy->uuid <= 0) {
2453 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002454 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002455 err_code |= ERR_ALERT | ERR_FATAL;
2456 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002457 }
2458
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002459 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2460 if (node) {
2461 struct proxy *target = container_of(node, struct proxy, conf.id);
2462 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2463 file, linenum, proxy_type_str(curproxy), curproxy->id,
2464 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2465 err_code |= ERR_ALERT | ERR_FATAL;
2466 goto out;
2467 }
2468 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002469 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002470 else if (!strcmp(args[0], "description")) {
2471 int i, len=0;
2472 char *d;
2473
Cyril Bonté99ed3272010-01-24 23:29:44 +01002474 if (curproxy == &defproxy) {
2475 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2476 file, linenum, args[0]);
2477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
2479 }
2480
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002481 if (!*args[1]) {
2482 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2483 file, linenum, args[0]);
2484 return -1;
2485 }
2486
Willy Tarreau348acfe2014-04-14 15:00:39 +02002487 for (i = 1; *args[i]; i++)
2488 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002489
2490 d = (char *)calloc(1, len);
2491 curproxy->desc = d;
2492
Willy Tarreau348acfe2014-04-14 15:00:39 +02002493 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2494 for (i = 2; *args[i]; i++)
2495 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002496
2497 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002498 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2499 curproxy->state = PR_STSTOPPED;
2500 }
2501 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2502 curproxy->state = PR_STNEW;
2503 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002504 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2505 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002506 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002507
2508 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002509 unsigned int low, high;
2510
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002511 if (strcmp(args[cur_arg], "all") == 0) {
2512 set = 0;
2513 break;
2514 }
2515 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002516 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002517 }
2518 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002519 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002520 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002521 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002522 char *dash = strchr(args[cur_arg], '-');
2523
2524 low = high = str2uic(args[cur_arg]);
2525 if (dash)
2526 high = str2uic(dash + 1);
2527
2528 if (high < low) {
2529 unsigned int swap = low;
2530 low = high;
2531 high = swap;
2532 }
2533
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002534 if (low < 1 || high > LONGBITS) {
2535 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2536 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002537 err_code |= ERR_ALERT | ERR_FATAL;
2538 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002539 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002540 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002541 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002542 }
2543 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002544 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2545 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002546 err_code |= ERR_ALERT | ERR_FATAL;
2547 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002548 }
2549 cur_arg++;
2550 }
2551 curproxy->bind_proc = set;
2552 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002553 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002554 if (curproxy == &defproxy) {
2555 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002556 err_code |= ERR_ALERT | ERR_FATAL;
2557 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002558 }
2559
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002560 err = invalid_char(args[1]);
2561 if (err) {
2562 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2563 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002564 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002565 }
2566
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002567 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002568 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2569 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002570 err_code |= ERR_ALERT | ERR_FATAL;
2571 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002572 }
2573 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2575 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576
Willy Tarreau977b8e42006-12-29 14:19:17 +01002577 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002578 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002579
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 if (*(args[1]) == 0) {
2581 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2582 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002583 err_code |= ERR_ALERT | ERR_FATAL;
2584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002586
Willy Tarreau67402132012-05-31 20:40:20 +02002587 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002588 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002589 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002590 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002591 curproxy->cookie_name = strdup(args[1]);
2592 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002593
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594 cur_arg = 2;
2595 while (*(args[cur_arg])) {
2596 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002597 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598 }
2599 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002600 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002601 }
2602 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002603 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604 }
2605 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002606 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607 }
2608 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002609 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002610 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002611 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002612 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002613 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002615 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002616 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002617 else if (!strcmp(args[cur_arg], "httponly")) {
2618 curproxy->ck_opts |= PR_CK_HTTPONLY;
2619 }
2620 else if (!strcmp(args[cur_arg], "secure")) {
2621 curproxy->ck_opts |= PR_CK_SECURE;
2622 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002623 else if (!strcmp(args[cur_arg], "domain")) {
2624 if (!*args[cur_arg + 1]) {
2625 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2626 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002627 err_code |= ERR_ALERT | ERR_FATAL;
2628 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002629 }
2630
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002631 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002632 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002633 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2634 " dots nor does not start with a dot."
2635 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002636 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002637 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002638 }
2639
2640 err = invalid_domainchar(args[cur_arg + 1]);
2641 if (err) {
2642 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2643 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002644 err_code |= ERR_ALERT | ERR_FATAL;
2645 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002646 }
2647
Willy Tarreau68a897b2009-12-03 23:28:34 +01002648 if (!curproxy->cookie_domain) {
2649 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2650 } else {
2651 /* one domain was already specified, add another one by
2652 * building the string which will be returned along with
2653 * the cookie.
2654 */
2655 char *new_ptr;
2656 int new_len = strlen(curproxy->cookie_domain) +
2657 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2658 new_ptr = malloc(new_len);
2659 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2660 free(curproxy->cookie_domain);
2661 curproxy->cookie_domain = new_ptr;
2662 }
Willy Tarreau31936852010-10-06 16:59:56 +02002663 cur_arg++;
2664 }
2665 else if (!strcmp(args[cur_arg], "maxidle")) {
2666 unsigned int maxidle;
2667 const char *res;
2668
2669 if (!*args[cur_arg + 1]) {
2670 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2671 file, linenum, args[cur_arg]);
2672 err_code |= ERR_ALERT | ERR_FATAL;
2673 goto out;
2674 }
2675
2676 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2677 if (res) {
2678 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2679 file, linenum, *res, args[cur_arg]);
2680 err_code |= ERR_ALERT | ERR_FATAL;
2681 goto out;
2682 }
2683 curproxy->cookie_maxidle = maxidle;
2684 cur_arg++;
2685 }
2686 else if (!strcmp(args[cur_arg], "maxlife")) {
2687 unsigned int maxlife;
2688 const char *res;
2689
2690 if (!*args[cur_arg + 1]) {
2691 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2692 file, linenum, args[cur_arg]);
2693 err_code |= ERR_ALERT | ERR_FATAL;
2694 goto out;
2695 }
2696
2697 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2698 if (res) {
2699 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2700 file, linenum, *res, args[cur_arg]);
2701 err_code |= ERR_ALERT | ERR_FATAL;
2702 goto out;
2703 }
2704 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002705 cur_arg++;
2706 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002707 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002708 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 +02002709 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002712 }
2713 cur_arg++;
2714 }
Willy Tarreau67402132012-05-31 20:40:20 +02002715 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002716 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2717 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002718 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002719 }
2720
Willy Tarreau67402132012-05-31 20:40:20 +02002721 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002722 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2723 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002724 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002725 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002726
Willy Tarreau67402132012-05-31 20:40:20 +02002727 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002728 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2729 file, linenum);
2730 err_code |= ERR_ALERT | ERR_FATAL;
2731 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002732 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman98637e52014-06-20 12:30:16 +09002733 else if (!strcmp(args[0], "external-check")) {
2734 if (*(args[1]) == 0) {
2735 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2736 file, linenum, args[0]);
2737 err_code |= ERR_ALERT | ERR_FATAL;
2738 goto out;
2739 }
2740
2741 if (!strcmp(args[1], "command")) {
2742 if (*(args[1]) == 0) {
2743 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2744 file, linenum, args[1]);
2745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
2747 }
2748 free(curproxy->check_command);
2749 curproxy->check_command = strdup(args[2]);
2750 }
2751 else if (!strcmp(args[1], "path")) {
2752 if (*(args[1]) == 0) {
2753 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2754 file, linenum, args[1]);
2755 err_code |= ERR_ALERT | ERR_FATAL;
2756 goto out;
2757 }
2758 free(curproxy->check_path);
2759 curproxy->check_path = strdup(args[2]);
2760 }
2761 else {
2762 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
2763 file, linenum, args[1]);
2764 err_code |= ERR_ALERT | ERR_FATAL;
2765 goto out;
2766 }
2767 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002768 else if (!strcmp(args[0], "persist")) { /* persist */
2769 if (*(args[1]) == 0) {
2770 Alert("parsing [%s:%d] : missing persist method.\n",
2771 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002772 err_code |= ERR_ALERT | ERR_FATAL;
2773 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002774 }
2775
2776 if (!strncmp(args[1], "rdp-cookie", 10)) {
2777 curproxy->options2 |= PR_O2_RDPC_PRST;
2778
Emeric Brunb982a3d2010-01-04 15:45:53 +01002779 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002780 const char *beg, *end;
2781
2782 beg = args[1] + 11;
2783 end = strchr(beg, ')');
2784
2785 if (!end || end == beg) {
2786 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2787 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002788 err_code |= ERR_ALERT | ERR_FATAL;
2789 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002790 }
2791
2792 free(curproxy->rdp_cookie_name);
2793 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2794 curproxy->rdp_cookie_len = end-beg;
2795 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002796 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002797 free(curproxy->rdp_cookie_name);
2798 curproxy->rdp_cookie_name = strdup("msts");
2799 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2800 }
2801 else { /* syntax */
2802 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2803 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002806 }
2807 }
2808 else {
2809 Alert("parsing [%s:%d] : unknown persist method.\n",
2810 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002811 err_code |= ERR_ALERT | ERR_FATAL;
2812 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002813 }
2814 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002815 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002816 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002817
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002818 if (curproxy == &defproxy) {
2819 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
2822 }
2823
Willy Tarreau977b8e42006-12-29 14:19:17 +01002824 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002825 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002826
Willy Tarreaubaaee002006-06-26 02:48:02 +02002827 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002828 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002829 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002830 err_code |= ERR_ALERT | ERR_FATAL;
2831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002832 }
2833 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002834 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002835 curproxy->appsession_name = strdup(args[1]);
2836 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2837 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002838 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2839 if (err) {
2840 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2841 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002844 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002845 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002846
Willy Tarreau51041c72007-09-09 21:56:53 +02002847 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2848 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002849 err_code |= ERR_ALERT | ERR_ABORT;
2850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002852
2853 cur_arg = 6;
2854 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002855 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2856 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002857 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002858 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002859 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002860 } else if (!strcmp(args[cur_arg], "prefix")) {
2861 curproxy->options2 |= PR_O2_AS_PFX;
2862 } else if (!strcmp(args[cur_arg], "mode")) {
2863 if (!*args[cur_arg + 1]) {
2864 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2865 file, linenum, args[0], args[cur_arg]);
2866 err_code |= ERR_ALERT | ERR_FATAL;
2867 goto out;
2868 }
2869
2870 cur_arg++;
2871 if (!strcmp(args[cur_arg], "query-string")) {
2872 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2873 curproxy->options2 |= PR_O2_AS_M_QS;
2874 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2875 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2876 curproxy->options2 |= PR_O2_AS_M_PP;
2877 } else {
2878 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
2881 }
2882 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002883 cur_arg++;
2884 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002885 } /* Url App Session */
2886 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002887 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002888 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002889
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002891 if (curproxy == &defproxy) {
2892 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
2895 }
2896
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 if (*(args[4]) == 0) {
2898 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2899 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002900 err_code |= ERR_ALERT | ERR_FATAL;
2901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002902 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002903 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002904 curproxy->capture_name = strdup(args[2]);
2905 curproxy->capture_namelen = strlen(curproxy->capture_name);
2906 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002907 curproxy->to_log |= LW_COOKIE;
2908 }
2909 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2910 struct cap_hdr *hdr;
2911
2912 if (curproxy == &defproxy) {
2913 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 +02002914 err_code |= ERR_ALERT | ERR_FATAL;
2915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916 }
2917
2918 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2919 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2920 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002923 }
2924
2925 hdr = calloc(sizeof(struct cap_hdr), 1);
2926 hdr->next = curproxy->req_cap;
2927 hdr->name = strdup(args[3]);
2928 hdr->namelen = strlen(args[3]);
2929 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002930 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002931 hdr->index = curproxy->nb_req_cap++;
2932 curproxy->req_cap = hdr;
2933 curproxy->to_log |= LW_REQHDR;
2934 }
2935 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2936 struct cap_hdr *hdr;
2937
2938 if (curproxy == &defproxy) {
2939 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 +02002940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002942 }
2943
2944 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2945 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2946 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002947 err_code |= ERR_ALERT | ERR_FATAL;
2948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002949 }
2950 hdr = calloc(sizeof(struct cap_hdr), 1);
2951 hdr->next = curproxy->rsp_cap;
2952 hdr->name = strdup(args[3]);
2953 hdr->namelen = strlen(args[3]);
2954 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002955 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002956 hdr->index = curproxy->nb_rsp_cap++;
2957 curproxy->rsp_cap = hdr;
2958 curproxy->to_log |= LW_RSPHDR;
2959 }
2960 else {
2961 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2962 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002965 }
2966 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002967 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002968 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002969 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002970
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 if (*(args[1]) == 0) {
2972 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2973 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002974 err_code |= ERR_ALERT | ERR_FATAL;
2975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002976 }
2977 curproxy->conn_retries = atol(args[1]);
2978 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002979 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002980 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002981
2982 if (curproxy == &defproxy) {
2983 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2984 err_code |= ERR_ALERT | ERR_FATAL;
2985 goto out;
2986 }
2987
Willy Tarreau20b0de52012-12-24 15:45:22 +01002988 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2989 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2990 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2991 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002992 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002993 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2994 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 +01002995 file, linenum, args[0]);
2996 err_code |= ERR_WARN;
2997 }
2998
Willy Tarreauff011f22011-01-06 17:51:27 +01002999 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003000
Willy Tarreauff011f22011-01-06 17:51:27 +01003001 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003002 err_code |= ERR_ALERT | ERR_ABORT;
3003 goto out;
3004 }
3005
Willy Tarreau5002f572014-04-23 01:32:02 +02003006 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003007 err_code |= warnif_cond_conflicts(rule->cond,
3008 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3009 file, linenum);
3010
Willy Tarreauff011f22011-01-06 17:51:27 +01003011 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003012 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003013 else if (!strcmp(args[0], "http-response")) { /* response access control */
3014 struct http_res_rule *rule;
3015
3016 if (curproxy == &defproxy) {
3017 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
3020 }
3021
3022 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3023 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3024 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3025 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3026 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3027 file, linenum, args[0]);
3028 err_code |= ERR_WARN;
3029 }
3030
3031 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3032
3033 if (!rule) {
3034 err_code |= ERR_ALERT | ERR_ABORT;
3035 goto out;
3036 }
3037
3038 err_code |= warnif_cond_conflicts(rule->cond,
3039 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3040 file, linenum);
3041
3042 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3043 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003044 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3045 /* set the header name and length into the proxy structure */
3046 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3047 err_code |= ERR_WARN;
3048
3049 if (!*args[1]) {
3050 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3051 file, linenum, args[0]);
3052 err_code |= ERR_ALERT | ERR_FATAL;
3053 goto out;
3054 }
3055
3056 /* set the desired header name */
3057 free(curproxy->server_id_hdr_name);
3058 curproxy->server_id_hdr_name = strdup(args[1]);
3059 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3060 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003061 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003062 struct http_req_rule *rule;
3063
Willy Tarreaub099aca2008-10-12 17:26:37 +02003064 if (curproxy == &defproxy) {
3065 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003066 err_code |= ERR_ALERT | ERR_FATAL;
3067 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003068 }
3069
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003070 /* emulate "block" using "http-request block". Since these rules are supposed to
3071 * be processed before all http-request rules, we put them into their own list
3072 * and will insert them at the end.
3073 */
3074 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3075 if (!rule) {
3076 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003077 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003078 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003079 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3080 err_code |= warnif_cond_conflicts(rule->cond,
3081 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3082 file, linenum);
3083 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003084
3085 if (!already_warned(WARN_BLOCK_DEPRECATED))
3086 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]);
3087
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003088 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003089 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003090 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003091
Cyril Bonté99ed3272010-01-24 23:29:44 +01003092 if (curproxy == &defproxy) {
3093 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
3096 }
3097
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003098 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003099 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3100 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003103 }
3104
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003105 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003106 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003107 err_code |= warnif_cond_conflicts(rule->cond,
3108 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3109 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003110 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003111 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003112 struct switching_rule *rule;
3113
Willy Tarreaub099aca2008-10-12 17:26:37 +02003114 if (curproxy == &defproxy) {
3115 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003118 }
3119
Willy Tarreau55ea7572007-06-17 19:56:27 +02003120 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003121 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003122
3123 if (*(args[1]) == 0) {
3124 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003127 }
3128
Willy Tarreauf51658d2014-04-23 01:21:56 +02003129 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3130 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3131 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3132 file, linenum, errmsg);
3133 err_code |= ERR_ALERT | ERR_FATAL;
3134 goto out;
3135 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003136
Willy Tarreauf51658d2014-04-23 01:21:56 +02003137 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003138 }
3139
3140 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3141 rule->cond = cond;
3142 rule->be.name = strdup(args[1]);
3143 LIST_INIT(&rule->list);
3144 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3145 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003146 else if (strcmp(args[0], "use-server") == 0) {
3147 struct server_rule *rule;
3148
3149 if (curproxy == &defproxy) {
3150 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3151 err_code |= ERR_ALERT | ERR_FATAL;
3152 goto out;
3153 }
3154
3155 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3156 err_code |= ERR_WARN;
3157
3158 if (*(args[1]) == 0) {
3159 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3160 err_code |= ERR_ALERT | ERR_FATAL;
3161 goto out;
3162 }
3163
3164 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3165 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3166 file, linenum, args[0]);
3167 err_code |= ERR_ALERT | ERR_FATAL;
3168 goto out;
3169 }
3170
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003171 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3172 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3173 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
3176 }
3177
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003178 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003179
3180 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3181 rule->cond = cond;
3182 rule->srv.name = strdup(args[1]);
3183 LIST_INIT(&rule->list);
3184 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3185 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3186 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003187 else if ((!strcmp(args[0], "force-persist")) ||
3188 (!strcmp(args[0], "ignore-persist"))) {
3189 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003190
3191 if (curproxy == &defproxy) {
3192 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3193 err_code |= ERR_ALERT | ERR_FATAL;
3194 goto out;
3195 }
3196
3197 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3198 err_code |= ERR_WARN;
3199
Willy Tarreauef6494c2010-01-28 17:12:36 +01003200 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003201 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3202 file, linenum, args[0]);
3203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
3205 }
3206
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003207 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3208 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3209 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003210 err_code |= ERR_ALERT | ERR_FATAL;
3211 goto out;
3212 }
3213
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003214 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3215 * where force-persist is applied.
3216 */
3217 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003218
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003219 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003220 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003221 if (!strcmp(args[0], "force-persist")) {
3222 rule->type = PERSIST_TYPE_FORCE;
3223 } else {
3224 rule->type = PERSIST_TYPE_IGNORE;
3225 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003226 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003227 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003228 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003229 else if (!strcmp(args[0], "stick-table")) {
3230 int myidx = 1;
3231
Emeric Brun32da3c42010-09-23 18:39:19 +02003232 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003233 curproxy->table.type = (unsigned int)-1;
3234 while (*args[myidx]) {
3235 const char *err;
3236
3237 if (strcmp(args[myidx], "size") == 0) {
3238 myidx++;
3239 if (!*(args[myidx])) {
3240 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3241 file, linenum, args[myidx-1]);
3242 err_code |= ERR_ALERT | ERR_FATAL;
3243 goto out;
3244 }
3245 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3246 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3247 file, linenum, *err, args[myidx-1]);
3248 err_code |= ERR_ALERT | ERR_FATAL;
3249 goto out;
3250 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003251 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003252 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003253 else if (strcmp(args[myidx], "peers") == 0) {
3254 myidx++;
Godbach50523162013-12-11 19:48:57 +08003255 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003256 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3257 file, linenum, args[myidx-1]);
3258 err_code |= ERR_ALERT | ERR_FATAL;
3259 goto out;
Godbach50523162013-12-11 19:48:57 +08003260 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003261 curproxy->table.peers.name = strdup(args[myidx++]);
3262 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003263 else if (strcmp(args[myidx], "expire") == 0) {
3264 myidx++;
3265 if (!*(args[myidx])) {
3266 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3267 file, linenum, args[myidx-1]);
3268 err_code |= ERR_ALERT | ERR_FATAL;
3269 goto out;
3270 }
3271 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3272 if (err) {
3273 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3274 file, linenum, *err, args[myidx-1]);
3275 err_code |= ERR_ALERT | ERR_FATAL;
3276 goto out;
3277 }
3278 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003279 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003280 }
3281 else if (strcmp(args[myidx], "nopurge") == 0) {
3282 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003283 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003284 }
3285 else if (strcmp(args[myidx], "type") == 0) {
3286 myidx++;
3287 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3288 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3289 file, linenum, args[myidx]);
3290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
3292 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003293 /* myidx already points to next arg */
3294 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003295 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003296 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003297 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003298
3299 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003300 nw = args[myidx];
3301 while (*nw) {
3302 /* the "store" keyword supports a comma-separated list */
3303 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003304 sa = NULL; /* store arg */
3305 while (*nw && *nw != ',') {
3306 if (*nw == '(') {
3307 *nw = 0;
3308 sa = ++nw;
3309 while (*nw != ')') {
3310 if (!*nw) {
3311 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3312 file, linenum, args[0], cw);
3313 err_code |= ERR_ALERT | ERR_FATAL;
3314 goto out;
3315 }
3316 nw++;
3317 }
3318 *nw = '\0';
3319 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003320 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003321 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003322 if (*nw)
3323 *nw++ = '\0';
3324 type = stktable_get_data_type(cw);
3325 if (type < 0) {
3326 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3327 file, linenum, args[0], cw);
3328 err_code |= ERR_ALERT | ERR_FATAL;
3329 goto out;
3330 }
Willy Tarreauac782882010-06-20 10:41:54 +02003331
3332 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3333 switch (err) {
3334 case PE_NONE: break;
3335 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003336 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3337 file, linenum, args[0], cw);
3338 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003339 break;
3340
3341 case PE_ARG_MISSING:
3342 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3343 file, linenum, args[0], cw);
3344 err_code |= ERR_ALERT | ERR_FATAL;
3345 goto out;
3346
3347 case PE_ARG_NOT_USED:
3348 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3349 file, linenum, args[0], cw);
3350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
3352
3353 default:
3354 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3355 file, linenum, args[0], cw);
3356 err_code |= ERR_ALERT | ERR_FATAL;
3357 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003358 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003359 }
3360 myidx++;
3361 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003362 else {
3363 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3364 file, linenum, args[myidx]);
3365 err_code |= ERR_ALERT | ERR_FATAL;
3366 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003367 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003368 }
3369
3370 if (!curproxy->table.size) {
3371 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3372 file, linenum);
3373 err_code |= ERR_ALERT | ERR_FATAL;
3374 goto out;
3375 }
3376
3377 if (curproxy->table.type == (unsigned int)-1) {
3378 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3379 file, linenum);
3380 err_code |= ERR_ALERT | ERR_FATAL;
3381 goto out;
3382 }
3383 }
3384 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003385 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003386 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003387 int myidx = 0;
3388 const char *name = NULL;
3389 int flags;
3390
3391 if (curproxy == &defproxy) {
3392 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3393 err_code |= ERR_ALERT | ERR_FATAL;
3394 goto out;
3395 }
3396
3397 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3398 err_code |= ERR_WARN;
3399 goto out;
3400 }
3401
3402 myidx++;
3403 if ((strcmp(args[myidx], "store") == 0) ||
3404 (strcmp(args[myidx], "store-request") == 0)) {
3405 myidx++;
3406 flags = STK_IS_STORE;
3407 }
3408 else if (strcmp(args[myidx], "store-response") == 0) {
3409 myidx++;
3410 flags = STK_IS_STORE | STK_ON_RSP;
3411 }
3412 else if (strcmp(args[myidx], "match") == 0) {
3413 myidx++;
3414 flags = STK_IS_MATCH;
3415 }
3416 else if (strcmp(args[myidx], "on") == 0) {
3417 myidx++;
3418 flags = STK_IS_MATCH | STK_IS_STORE;
3419 }
3420 else {
3421 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3422 err_code |= ERR_ALERT | ERR_FATAL;
3423 goto out;
3424 }
3425
3426 if (*(args[myidx]) == 0) {
3427 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3428 err_code |= ERR_ALERT | ERR_FATAL;
3429 goto out;
3430 }
3431
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003432 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003433 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003434 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003435 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003436 err_code |= ERR_ALERT | ERR_FATAL;
3437 goto out;
3438 }
3439
3440 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003441 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3442 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3443 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003444 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003445 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003446 goto out;
3447 }
3448 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003449 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3450 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3451 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003452 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003453 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003454 goto out;
3455 }
3456 }
3457
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003458 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003459 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003460
Emeric Brunb982a3d2010-01-04 15:45:53 +01003461 if (strcmp(args[myidx], "table") == 0) {
3462 myidx++;
3463 name = args[myidx++];
3464 }
3465
Willy Tarreauef6494c2010-01-28 17:12:36 +01003466 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003467 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3468 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3469 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003470 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003471 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003472 goto out;
3473 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003474 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003475 else if (*(args[myidx])) {
3476 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3477 file, linenum, args[0], args[myidx]);
3478 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003479 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003480 goto out;
3481 }
Emeric Brun97679e72010-09-23 17:56:44 +02003482 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003483 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003484 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003485 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003486
Emeric Brunb982a3d2010-01-04 15:45:53 +01003487 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3488 rule->cond = cond;
3489 rule->expr = expr;
3490 rule->flags = flags;
3491 rule->table.name = name ? strdup(name) : NULL;
3492 LIST_INIT(&rule->list);
3493 if (flags & STK_ON_RSP)
3494 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3495 else
3496 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3497 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003498 else if (!strcmp(args[0], "stats")) {
3499 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3500 curproxy->uri_auth = NULL; /* we must detach from the default config */
3501
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003502 if (!*args[1]) {
3503 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003504 } else if (!strcmp(args[1], "admin")) {
3505 struct stats_admin_rule *rule;
3506
3507 if (curproxy == &defproxy) {
3508 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3509 err_code |= ERR_ALERT | ERR_FATAL;
3510 goto out;
3511 }
3512
3513 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3514 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3515 err_code |= ERR_ALERT | ERR_ABORT;
3516 goto out;
3517 }
3518
3519 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3520 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3521 file, linenum, args[0], args[1]);
3522 err_code |= ERR_ALERT | ERR_FATAL;
3523 goto out;
3524 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003525 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3526 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3527 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003528 err_code |= ERR_ALERT | ERR_FATAL;
3529 goto out;
3530 }
3531
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003532 err_code |= warnif_cond_conflicts(cond,
3533 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3534 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003535
3536 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3537 rule->cond = cond;
3538 LIST_INIT(&rule->list);
3539 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003540 } else if (!strcmp(args[1], "uri")) {
3541 if (*(args[2]) == 0) {
3542 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003543 err_code |= ERR_ALERT | ERR_FATAL;
3544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003545 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3546 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003547 err_code |= ERR_ALERT | ERR_ABORT;
3548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003549 }
3550 } else if (!strcmp(args[1], "realm")) {
3551 if (*(args[2]) == 0) {
3552 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003555 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3556 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003557 err_code |= ERR_ALERT | ERR_ABORT;
3558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003559 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003560 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003561 unsigned interval;
3562
3563 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3564 if (err) {
3565 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3566 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003567 err_code |= ERR_ALERT | ERR_FATAL;
3568 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003569 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3570 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003571 err_code |= ERR_ALERT | ERR_ABORT;
3572 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003573 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003574 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003575 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003576
3577 if (curproxy == &defproxy) {
3578 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3579 err_code |= ERR_ALERT | ERR_FATAL;
3580 goto out;
3581 }
3582
3583 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3584 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3585 err_code |= ERR_ALERT | ERR_ABORT;
3586 goto out;
3587 }
3588
Willy Tarreauff011f22011-01-06 17:51:27 +01003589 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3590 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003591 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3592 file, linenum, args[0]);
3593 err_code |= ERR_WARN;
3594 }
3595
Willy Tarreauff011f22011-01-06 17:51:27 +01003596 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003597
Willy Tarreauff011f22011-01-06 17:51:27 +01003598 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003599 err_code |= ERR_ALERT | ERR_ABORT;
3600 goto out;
3601 }
3602
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003603 err_code |= warnif_cond_conflicts(rule->cond,
3604 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3605 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003606 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003607
Willy Tarreaubaaee002006-06-26 02:48:02 +02003608 } else if (!strcmp(args[1], "auth")) {
3609 if (*(args[2]) == 0) {
3610 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003611 err_code |= ERR_ALERT | ERR_FATAL;
3612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3614 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003615 err_code |= ERR_ALERT | ERR_ABORT;
3616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003617 }
3618 } else if (!strcmp(args[1], "scope")) {
3619 if (*(args[2]) == 0) {
3620 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003621 err_code |= ERR_ALERT | ERR_FATAL;
3622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003623 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3624 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003625 err_code |= ERR_ALERT | ERR_ABORT;
3626 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 }
3628 } else if (!strcmp(args[1], "enable")) {
3629 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3630 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003631 err_code |= ERR_ALERT | ERR_ABORT;
3632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003634 } else if (!strcmp(args[1], "hide-version")) {
3635 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3636 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_ALERT | ERR_ABORT;
3638 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003639 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003640 } else if (!strcmp(args[1], "show-legends")) {
3641 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3642 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3643 err_code |= ERR_ALERT | ERR_ABORT;
3644 goto out;
3645 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003646 } else if (!strcmp(args[1], "show-node")) {
3647
3648 if (*args[2]) {
3649 int i;
3650 char c;
3651
3652 for (i=0; args[2][i]; i++) {
3653 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003654 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3655 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003656 break;
3657 }
3658
3659 if (!i || args[2][i]) {
3660 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3661 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3662 file, linenum, args[0], args[1]);
3663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
3665 }
3666 }
3667
3668 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3669 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3670 err_code |= ERR_ALERT | ERR_ABORT;
3671 goto out;
3672 }
3673 } else if (!strcmp(args[1], "show-desc")) {
3674 char *desc = NULL;
3675
3676 if (*args[2]) {
3677 int i, len=0;
3678 char *d;
3679
Willy Tarreau348acfe2014-04-14 15:00:39 +02003680 for (i = 2; *args[i]; i++)
3681 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003682
3683 desc = d = (char *)calloc(1, len);
3684
Willy Tarreau348acfe2014-04-14 15:00:39 +02003685 d += snprintf(d, desc + len - d, "%s", args[2]);
3686 for (i = 3; *args[i]; i++)
3687 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003688 }
3689
3690 if (!*args[2] && !global.desc)
3691 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3692 file, linenum, args[1]);
3693 else {
3694 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3695 free(desc);
3696 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3697 err_code |= ERR_ALERT | ERR_ABORT;
3698 goto out;
3699 }
3700 free(desc);
3701 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003703stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003704 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 +01003705 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003706 err_code |= ERR_ALERT | ERR_FATAL;
3707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003708 }
3709 }
3710 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003711 int optnum;
3712
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003713 if (*(args[1]) == '\0') {
3714 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3715 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003716 err_code |= ERR_ALERT | ERR_FATAL;
3717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003718 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003719
3720 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3721 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003722 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3723 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3724 file, linenum, cfg_opts[optnum].name);
3725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
3727 }
Willy Tarreau93893792009-07-23 13:19:11 +02003728 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3729 err_code |= ERR_WARN;
3730 goto out;
3731 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003732
Willy Tarreau3842f002009-06-14 11:39:52 +02003733 curproxy->no_options &= ~cfg_opts[optnum].val;
3734 curproxy->options &= ~cfg_opts[optnum].val;
3735
3736 switch (kwm) {
3737 case KWM_STD:
3738 curproxy->options |= cfg_opts[optnum].val;
3739 break;
3740 case KWM_NO:
3741 curproxy->no_options |= cfg_opts[optnum].val;
3742 break;
3743 case KWM_DEF: /* already cleared */
3744 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003745 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003746
Willy Tarreau93893792009-07-23 13:19:11 +02003747 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003748 }
3749 }
3750
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003751 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3752 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003753 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3754 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3755 file, linenum, cfg_opts2[optnum].name);
3756 err_code |= ERR_ALERT | ERR_FATAL;
3757 goto out;
3758 }
Willy Tarreau93893792009-07-23 13:19:11 +02003759 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3760 err_code |= ERR_WARN;
3761 goto out;
3762 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003763
Willy Tarreau3842f002009-06-14 11:39:52 +02003764 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3765 curproxy->options2 &= ~cfg_opts2[optnum].val;
3766
3767 switch (kwm) {
3768 case KWM_STD:
3769 curproxy->options2 |= cfg_opts2[optnum].val;
3770 break;
3771 case KWM_NO:
3772 curproxy->no_options2 |= cfg_opts2[optnum].val;
3773 break;
3774 case KWM_DEF: /* already cleared */
3775 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003776 }
Willy Tarreau93893792009-07-23 13:19:11 +02003777 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003778 }
3779 }
3780
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003781 /* HTTP options override each other. They can be cancelled using
3782 * "no option xxx" which only switches to default mode if the mode
3783 * was this one (useful for cancelling options set in defaults
3784 * sections).
3785 */
3786 if (strcmp(args[1], "httpclose") == 0) {
3787 if (kwm == KWM_STD) {
3788 curproxy->options &= ~PR_O_HTTP_MODE;
3789 curproxy->options |= PR_O_HTTP_PCL;
3790 goto out;
3791 }
3792 else if (kwm == KWM_NO) {
3793 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3794 curproxy->options &= ~PR_O_HTTP_MODE;
3795 goto out;
3796 }
3797 }
3798 else if (strcmp(args[1], "forceclose") == 0) {
3799 if (kwm == KWM_STD) {
3800 curproxy->options &= ~PR_O_HTTP_MODE;
3801 curproxy->options |= PR_O_HTTP_FCL;
3802 goto out;
3803 }
3804 else if (kwm == KWM_NO) {
3805 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3806 curproxy->options &= ~PR_O_HTTP_MODE;
3807 goto out;
3808 }
3809 }
3810 else if (strcmp(args[1], "http-server-close") == 0) {
3811 if (kwm == KWM_STD) {
3812 curproxy->options &= ~PR_O_HTTP_MODE;
3813 curproxy->options |= PR_O_HTTP_SCL;
3814 goto out;
3815 }
3816 else if (kwm == KWM_NO) {
3817 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3818 curproxy->options &= ~PR_O_HTTP_MODE;
3819 goto out;
3820 }
3821 }
3822 else if (strcmp(args[1], "http-keep-alive") == 0) {
3823 if (kwm == KWM_STD) {
3824 curproxy->options &= ~PR_O_HTTP_MODE;
3825 curproxy->options |= PR_O_HTTP_KAL;
3826 goto out;
3827 }
3828 else if (kwm == KWM_NO) {
3829 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3830 curproxy->options &= ~PR_O_HTTP_MODE;
3831 goto out;
3832 }
3833 }
3834 else if (strcmp(args[1], "http-tunnel") == 0) {
3835 if (kwm == KWM_STD) {
3836 curproxy->options &= ~PR_O_HTTP_MODE;
3837 curproxy->options |= PR_O_HTTP_TUN;
3838 goto out;
3839 }
3840 else if (kwm == KWM_NO) {
3841 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3842 curproxy->options &= ~PR_O_HTTP_MODE;
3843 goto out;
3844 }
3845 }
3846
Willy Tarreau3842f002009-06-14 11:39:52 +02003847 if (kwm != KWM_STD) {
3848 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003849 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003850 err_code |= ERR_ALERT | ERR_FATAL;
3851 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003852 }
3853
Emeric Brun3a058f32009-06-30 18:26:00 +02003854 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003855 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003856 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003857 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003858 if (*(args[2]) != '\0') {
3859 if (!strcmp(args[2], "clf")) {
3860 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003861 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003862 } else {
3863 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003864 err_code |= ERR_ALERT | ERR_FATAL;
3865 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003866 }
3867 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003868 if (curproxy->conf.logformat_string != default_http_log_format &&
3869 curproxy->conf.logformat_string != default_tcp_log_format &&
3870 curproxy->conf.logformat_string != clf_http_log_format)
3871 free(curproxy->conf.logformat_string);
3872 curproxy->conf.logformat_string = logformat;
3873
3874 free(curproxy->conf.lfs_file);
3875 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3876 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003877 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003878 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003879 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003880 if (curproxy->conf.logformat_string != default_http_log_format &&
3881 curproxy->conf.logformat_string != default_tcp_log_format &&
3882 curproxy->conf.logformat_string != clf_http_log_format)
3883 free(curproxy->conf.logformat_string);
3884 curproxy->conf.logformat_string = default_tcp_log_format;
3885
3886 free(curproxy->conf.lfs_file);
3887 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3888 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003889 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003890 else if (!strcmp(args[1], "tcpka")) {
3891 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003892 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003893 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003894
3895 if (curproxy->cap & PR_CAP_FE)
3896 curproxy->options |= PR_O_TCP_CLI_KA;
3897 if (curproxy->cap & PR_CAP_BE)
3898 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003899 }
3900 else if (!strcmp(args[1], "httpchk")) {
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;
3903
Willy Tarreaubaaee002006-06-26 02:48:02 +02003904 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003905 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003906 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003907 curproxy->options2 &= ~PR_O2_CHK_ANY;
3908 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003909 if (!*args[2]) { /* no argument */
3910 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3911 curproxy->check_len = strlen(DEF_CHECK_REQ);
3912 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003913 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003914 curproxy->check_req = (char *)malloc(reqlen);
3915 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003916 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003917 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003918 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003919 if (*args[4])
3920 reqlen += strlen(args[4]);
3921 else
3922 reqlen += strlen("HTTP/1.0");
3923
3924 curproxy->check_req = (char *)malloc(reqlen);
3925 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003926 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003927 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003928 }
3929 else if (!strcmp(args[1], "ssl-hello-chk")) {
3930 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003931 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003932 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003933
Willy Tarreaua534fea2008-08-03 12:19:50 +02003934 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003935 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003936 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003937 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003938 }
Willy Tarreau23677902007-05-08 23:50:35 +02003939 else if (!strcmp(args[1], "smtpchk")) {
3940 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003941 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003942 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003943 curproxy->options2 &= ~PR_O2_CHK_ANY;
3944 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003945
3946 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3947 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3948 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3949 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3950 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3951 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3952 curproxy->check_req = (char *)malloc(reqlen);
3953 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3954 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3955 } else {
3956 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3957 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3958 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3959 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3960 }
3961 }
3962 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003963 else if (!strcmp(args[1], "pgsql-check")) {
3964 /* use PostgreSQL request to check servers' health */
3965 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3966 err_code |= ERR_WARN;
3967
3968 free(curproxy->check_req);
3969 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003970 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003971 curproxy->options2 |= PR_O2_PGSQL_CHK;
3972
3973 if (*(args[2])) {
3974 int cur_arg = 2;
3975
3976 while (*(args[cur_arg])) {
3977 if (strcmp(args[cur_arg], "user") == 0) {
3978 char * packet;
3979 uint32_t packet_len;
3980 uint32_t pv;
3981
3982 /* suboption header - needs additional argument for it */
3983 if (*(args[cur_arg+1]) == 0) {
3984 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3985 file, linenum, args[0], args[1], args[cur_arg]);
3986 err_code |= ERR_ALERT | ERR_FATAL;
3987 goto out;
3988 }
3989
3990 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3991 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3992 pv = htonl(0x30000); /* protocol version 3.0 */
3993
3994 packet = (char*) calloc(1, packet_len);
3995
3996 memcpy(packet + 4, &pv, 4);
3997
3998 /* copy "user" */
3999 memcpy(packet + 8, "user", 4);
4000
4001 /* copy username */
4002 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4003
4004 free(curproxy->check_req);
4005 curproxy->check_req = packet;
4006 curproxy->check_len = packet_len;
4007
4008 packet_len = htonl(packet_len);
4009 memcpy(packet, &packet_len, 4);
4010 cur_arg += 2;
4011 } else {
4012 /* unknown suboption - catchall */
4013 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4014 file, linenum, args[0], args[1]);
4015 err_code |= ERR_ALERT | ERR_FATAL;
4016 goto out;
4017 }
4018 } /* end while loop */
4019 }
4020 }
4021
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004022 else if (!strcmp(args[1], "redis-check")) {
4023 /* use REDIS PING request to check servers' health */
4024 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4025 err_code |= ERR_WARN;
4026
4027 free(curproxy->check_req);
4028 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004029 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004030 curproxy->options2 |= PR_O2_REDIS_CHK;
4031
4032 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4033 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4034 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4035 }
4036
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004037 else if (!strcmp(args[1], "mysql-check")) {
4038 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004039 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4040 err_code |= ERR_WARN;
4041
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004042 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004043 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004044 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004045 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004046
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004047 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004048 * const char mysql40_client_auth_pkt[] = {
4049 * "\x0e\x00\x00" // packet length
4050 * "\x01" // packet number
4051 * "\x00\x00" // client capabilities
4052 * "\x00\x00\x01" // max packet
4053 * "haproxy\x00" // username (null terminated string)
4054 * "\x00" // filler (always 0x00)
4055 * "\x01\x00\x00" // packet length
4056 * "\x00" // packet number
4057 * "\x01" // COM_QUIT command
4058 * };
4059 */
4060
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004061 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4062 * const char mysql41_client_auth_pkt[] = {
4063 * "\x0e\x00\x00\" // packet length
4064 * "\x01" // packet number
4065 * "\x00\x00\x00\x00" // client capabilities
4066 * "\x00\x00\x00\x01" // max packet
4067 * "\x21" // character set (UTF-8)
4068 * char[23] // All zeroes
4069 * "haproxy\x00" // username (null terminated string)
4070 * "\x00" // filler (always 0x00)
4071 * "\x01\x00\x00" // packet length
4072 * "\x00" // packet number
4073 * "\x01" // COM_QUIT command
4074 * };
4075 */
4076
4077
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004078 if (*(args[2])) {
4079 int cur_arg = 2;
4080
4081 while (*(args[cur_arg])) {
4082 if (strcmp(args[cur_arg], "user") == 0) {
4083 char *mysqluser;
4084 int packetlen, reqlen, userlen;
4085
4086 /* suboption header - needs additional argument for it */
4087 if (*(args[cur_arg+1]) == 0) {
4088 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4089 file, linenum, args[0], args[1], args[cur_arg]);
4090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
4092 }
4093 mysqluser = args[cur_arg + 1];
4094 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004095
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004096 if (*(args[cur_arg+2])) {
4097 if (!strcmp(args[cur_arg+2], "post-41")) {
4098 packetlen = userlen + 7 + 27;
4099 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004100
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004101 free(curproxy->check_req);
4102 curproxy->check_req = (char *)calloc(1, reqlen);
4103 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004104
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004105 snprintf(curproxy->check_req, 4, "%c%c%c",
4106 ((unsigned char) packetlen & 0xff),
4107 ((unsigned char) (packetlen >> 8) & 0xff),
4108 ((unsigned char) (packetlen >> 16) & 0xff));
4109
4110 curproxy->check_req[3] = 1;
4111 curproxy->check_req[5] = 130;
4112 curproxy->check_req[11] = 1;
4113 curproxy->check_req[12] = 33;
4114 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4115 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4116 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4117 cur_arg += 3;
4118 } else {
4119 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4120 err_code |= ERR_ALERT | ERR_FATAL;
4121 goto out;
4122 }
4123 } else {
4124 packetlen = userlen + 7;
4125 reqlen = packetlen + 9;
4126
4127 free(curproxy->check_req);
4128 curproxy->check_req = (char *)calloc(1, reqlen);
4129 curproxy->check_len = reqlen;
4130
4131 snprintf(curproxy->check_req, 4, "%c%c%c",
4132 ((unsigned char) packetlen & 0xff),
4133 ((unsigned char) (packetlen >> 8) & 0xff),
4134 ((unsigned char) (packetlen >> 16) & 0xff));
4135
4136 curproxy->check_req[3] = 1;
4137 curproxy->check_req[5] = 128;
4138 curproxy->check_req[8] = 1;
4139 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4140 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4141 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4142 cur_arg += 2;
4143 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004144 } else {
4145 /* unknown suboption - catchall */
4146 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4147 file, linenum, args[0], args[1]);
4148 err_code |= ERR_ALERT | ERR_FATAL;
4149 goto out;
4150 }
4151 } /* end while loop */
4152 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004153 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004154 else if (!strcmp(args[1], "ldap-check")) {
4155 /* use LDAP request to check servers' health */
4156 free(curproxy->check_req);
4157 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004158 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004159 curproxy->options2 |= PR_O2_LDAP_CHK;
4160
4161 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4162 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4163 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4164 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004165 else if (!strcmp(args[1], "tcp-check")) {
4166 /* use raw TCPCHK send/expect to check servers' health */
4167 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4168 err_code |= ERR_WARN;
4169
4170 free(curproxy->check_req);
4171 curproxy->check_req = NULL;
4172 curproxy->options2 &= ~PR_O2_CHK_ANY;
4173 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4174 }
Simon Horman98637e52014-06-20 12:30:16 +09004175 else if (!strcmp(args[1], "external-check")) {
4176 /* excute an external command to check servers' health */
4177 free(curproxy->check_req);
4178 curproxy->check_req = NULL;
4179 curproxy->options2 &= ~PR_O2_CHK_ANY;
4180 curproxy->options2 |= PR_O2_EXT_CHK;
4181 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004182 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004183 int cur_arg;
4184
4185 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4186 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004187 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004188
Willy Tarreau87cf5142011-08-19 22:57:24 +02004189 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004190
4191 free(curproxy->fwdfor_hdr_name);
4192 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4193 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4194
4195 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4196 cur_arg = 2;
4197 while (*(args[cur_arg])) {
4198 if (!strcmp(args[cur_arg], "except")) {
4199 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004200 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004201 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4202 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004203 err_code |= ERR_ALERT | ERR_FATAL;
4204 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004205 }
4206 /* flush useless bits */
4207 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004208 cur_arg += 2;
4209 } else if (!strcmp(args[cur_arg], "header")) {
4210 /* suboption header - needs additional argument for it */
4211 if (*(args[cur_arg+1]) == 0) {
4212 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4213 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004216 }
4217 free(curproxy->fwdfor_hdr_name);
4218 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4219 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4220 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004221 } else if (!strcmp(args[cur_arg], "if-none")) {
4222 curproxy->options &= ~PR_O_FF_ALWAYS;
4223 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004224 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004225 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004226 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004227 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004228 err_code |= ERR_ALERT | ERR_FATAL;
4229 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004230 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004231 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004232 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004233 else if (!strcmp(args[1], "originalto")) {
4234 int cur_arg;
4235
4236 /* insert x-original-to field, but not for the IP address listed as an except.
4237 * set default options (ie: bitfield, header name, etc)
4238 */
4239
4240 curproxy->options |= PR_O_ORGTO;
4241
4242 free(curproxy->orgto_hdr_name);
4243 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4244 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4245
Willy Tarreau87cf5142011-08-19 22:57:24 +02004246 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004247 cur_arg = 2;
4248 while (*(args[cur_arg])) {
4249 if (!strcmp(args[cur_arg], "except")) {
4250 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004251 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 +02004252 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4253 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004254 err_code |= ERR_ALERT | ERR_FATAL;
4255 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004256 }
4257 /* flush useless bits */
4258 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4259 cur_arg += 2;
4260 } else if (!strcmp(args[cur_arg], "header")) {
4261 /* suboption header - needs additional argument for it */
4262 if (*(args[cur_arg+1]) == 0) {
4263 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4264 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004267 }
4268 free(curproxy->orgto_hdr_name);
4269 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4270 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4271 cur_arg += 2;
4272 } else {
4273 /* unknown suboption - catchall */
4274 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4275 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004278 }
4279 } /* end while loop */
4280 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004281 else {
4282 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004283 err_code |= ERR_ALERT | ERR_FATAL;
4284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004285 }
Willy Tarreau93893792009-07-23 13:19:11 +02004286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004287 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004288 else if (!strcmp(args[0], "default_backend")) {
4289 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004290 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004291
4292 if (*(args[1]) == 0) {
4293 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004294 err_code |= ERR_ALERT | ERR_FATAL;
4295 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004296 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004297 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004298 curproxy->defbe.name = strdup(args[1]);
4299 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004300 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004301 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004302 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004303
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004304 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4305 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 +01004306 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004307 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004308 /* enable reconnections to dispatch */
4309 curproxy->options |= PR_O_REDISP;
4310 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004311 else if (!strcmp(args[0], "http-check")) {
4312 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004313 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004314
4315 if (strcmp(args[1], "disable-on-404") == 0) {
4316 /* enable a graceful server shutdown on an HTTP 404 response */
4317 curproxy->options |= PR_O_DISABLE404;
4318 }
Willy Tarreauef781042010-01-27 11:53:01 +01004319 else if (strcmp(args[1], "send-state") == 0) {
4320 /* enable emission of the apparent state of a server in HTTP checks */
4321 curproxy->options2 |= PR_O2_CHK_SNDST;
4322 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004323 else if (strcmp(args[1], "expect") == 0) {
4324 const char *ptr_arg;
4325 int cur_arg;
4326
4327 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4328 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4329 err_code |= ERR_ALERT | ERR_FATAL;
4330 goto out;
4331 }
4332
4333 cur_arg = 2;
4334 /* consider exclamation marks, sole or at the beginning of a word */
4335 while (*(ptr_arg = args[cur_arg])) {
4336 while (*ptr_arg == '!') {
4337 curproxy->options2 ^= PR_O2_EXP_INV;
4338 ptr_arg++;
4339 }
4340 if (*ptr_arg)
4341 break;
4342 cur_arg++;
4343 }
4344 /* now ptr_arg points to the beginning of a word past any possible
4345 * exclamation mark, and cur_arg is the argument which holds this word.
4346 */
4347 if (strcmp(ptr_arg, "status") == 0) {
4348 if (!*(args[cur_arg + 1])) {
4349 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4350 file, linenum, args[0], args[1], ptr_arg);
4351 err_code |= ERR_ALERT | ERR_FATAL;
4352 goto out;
4353 }
4354 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004355 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004356 curproxy->expect_str = strdup(args[cur_arg + 1]);
4357 }
4358 else if (strcmp(ptr_arg, "string") == 0) {
4359 if (!*(args[cur_arg + 1])) {
4360 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4361 file, linenum, args[0], args[1], ptr_arg);
4362 err_code |= ERR_ALERT | ERR_FATAL;
4363 goto out;
4364 }
4365 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004366 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004367 curproxy->expect_str = strdup(args[cur_arg + 1]);
4368 }
4369 else if (strcmp(ptr_arg, "rstatus") == 0) {
4370 if (!*(args[cur_arg + 1])) {
4371 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4372 file, linenum, args[0], args[1], ptr_arg);
4373 err_code |= ERR_ALERT | ERR_FATAL;
4374 goto out;
4375 }
4376 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004377 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004378 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004379 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004380 free(curproxy->expect_regex);
4381 curproxy->expect_regex = NULL;
4382 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004383 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004384 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4385 error = NULL;
4386 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4387 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4388 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4389 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
4392 }
4393 }
4394 else if (strcmp(ptr_arg, "rstring") == 0) {
4395 if (!*(args[cur_arg + 1])) {
4396 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4397 file, linenum, args[0], args[1], ptr_arg);
4398 err_code |= ERR_ALERT | ERR_FATAL;
4399 goto out;
4400 }
4401 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004402 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004403 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004404 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004405 free(curproxy->expect_regex);
4406 curproxy->expect_regex = NULL;
4407 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004408 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004409 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4410 error = NULL;
4411 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4412 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4413 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4414 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
4417 }
4418 }
4419 else {
4420 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4421 file, linenum, args[0], args[1], ptr_arg);
4422 err_code |= ERR_ALERT | ERR_FATAL;
4423 goto out;
4424 }
4425 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004426 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004427 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 +02004428 err_code |= ERR_ALERT | ERR_FATAL;
4429 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004430 }
4431 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004432 else if (!strcmp(args[0], "tcp-check")) {
4433 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4434 err_code |= ERR_WARN;
4435
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004436 if (strcmp(args[1], "connect") == 0) {
4437 const char *ptr_arg;
4438 int cur_arg;
4439 struct tcpcheck_rule *tcpcheck;
4440 struct list *l;
4441
4442 /* check if first rule is also a 'connect' action */
4443 l = (struct list *)&curproxy->tcpcheck_rules;
4444 if (l->p != l->n) {
4445 tcpcheck = (struct tcpcheck_rule *)l->n;
4446 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4447 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4448 file, linenum);
4449 err_code |= ERR_ALERT | ERR_FATAL;
4450 goto out;
4451 }
4452 }
4453
4454 cur_arg = 2;
4455 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4456 tcpcheck->action = TCPCHK_ACT_CONNECT;
4457
4458 /* parsing each parameters to fill up the rule */
4459 while (*(ptr_arg = args[cur_arg])) {
4460 /* tcp port */
4461 if (strcmp(args[cur_arg], "port") == 0) {
4462 if ( (atol(args[cur_arg + 1]) > 65535) ||
4463 (atol(args[cur_arg + 1]) < 1) ){
4464 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4465 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4466 err_code |= ERR_ALERT | ERR_FATAL;
4467 goto out;
4468 }
4469 tcpcheck->port = atol(args[cur_arg + 1]);
4470 cur_arg += 2;
4471 }
4472 /* send proxy protocol */
4473 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4474 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4475 cur_arg++;
4476 }
4477#ifdef USE_OPENSSL
4478 else if (strcmp(args[cur_arg], "ssl") == 0) {
4479 curproxy->options |= PR_O_TCPCHK_SSL;
4480 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4481 cur_arg++;
4482 }
4483#endif /* USE_OPENSSL */
4484 else {
4485#ifdef USE_OPENSSL
4486 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4487#else /* USE_OPENSSL */
4488 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4489#endif /* USE_OPENSSL */
4490 file, linenum, args[0], args[1], args[cur_arg]);
4491 err_code |= ERR_ALERT | ERR_FATAL;
4492 goto out;
4493 }
4494
4495 }
4496
4497 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4498 }
4499 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004500 if (! *(args[2]) ) {
4501 /* SEND string expected */
4502 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4503 file, linenum, args[0], args[1], args[2]);
4504 err_code |= ERR_ALERT | ERR_FATAL;
4505 goto out;
4506 } else {
4507 struct tcpcheck_rule *tcpcheck;
4508
4509 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4510
4511 tcpcheck->action = TCPCHK_ACT_SEND;
4512 tcpcheck->string_len = strlen(args[2]);
4513 tcpcheck->string = strdup(args[2]);
4514 tcpcheck->expect_regex = NULL;
4515
4516 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4517 }
4518 }
4519 else if (strcmp(args[1], "send-binary") == 0) {
4520 if (! *(args[2]) ) {
4521 /* SEND binary string expected */
4522 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4523 file, linenum, args[0], args[1], args[2]);
4524 err_code |= ERR_ALERT | ERR_FATAL;
4525 goto out;
4526 } else {
4527 struct tcpcheck_rule *tcpcheck;
4528 char *err = NULL;
4529
4530 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4531
4532 tcpcheck->action = TCPCHK_ACT_SEND;
4533 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4534 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4535 file, linenum, args[0], args[1], args[2], err);
4536 err_code |= ERR_ALERT | ERR_FATAL;
4537 goto out;
4538 }
4539 tcpcheck->expect_regex = NULL;
4540
4541 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4542 }
4543 }
4544 else if (strcmp(args[1], "expect") == 0) {
4545 const char *ptr_arg;
4546 int cur_arg;
4547 int inverse = 0;
4548
4549 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4550 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4551 err_code |= ERR_ALERT | ERR_FATAL;
4552 goto out;
4553 }
4554
4555 cur_arg = 2;
4556 /* consider exclamation marks, sole or at the beginning of a word */
4557 while (*(ptr_arg = args[cur_arg])) {
4558 while (*ptr_arg == '!') {
4559 inverse = !inverse;
4560 ptr_arg++;
4561 }
4562 if (*ptr_arg)
4563 break;
4564 cur_arg++;
4565 }
4566 /* now ptr_arg points to the beginning of a word past any possible
4567 * exclamation mark, and cur_arg is the argument which holds this word.
4568 */
4569 if (strcmp(ptr_arg, "binary") == 0) {
4570 if (!*(args[cur_arg + 1])) {
4571 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4572 file, linenum, args[0], args[1], ptr_arg);
4573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
4575 }
4576 struct tcpcheck_rule *tcpcheck;
4577 char *err = NULL;
4578
4579 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4580
4581 tcpcheck->action = TCPCHK_ACT_EXPECT;
4582 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4583 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4584 file, linenum, args[0], args[1], args[2], err);
4585 err_code |= ERR_ALERT | ERR_FATAL;
4586 goto out;
4587 }
4588 tcpcheck->expect_regex = NULL;
4589 tcpcheck->inverse = inverse;
4590
4591 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4592 }
4593 else if (strcmp(ptr_arg, "string") == 0) {
4594 if (!*(args[cur_arg + 1])) {
4595 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4596 file, linenum, args[0], args[1], ptr_arg);
4597 err_code |= ERR_ALERT | ERR_FATAL;
4598 goto out;
4599 }
4600 struct tcpcheck_rule *tcpcheck;
4601
4602 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4603
4604 tcpcheck->action = TCPCHK_ACT_EXPECT;
4605 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4606 tcpcheck->string = strdup(args[cur_arg + 1]);
4607 tcpcheck->expect_regex = NULL;
4608 tcpcheck->inverse = inverse;
4609
4610 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4611 }
4612 else if (strcmp(ptr_arg, "rstring") == 0) {
4613 if (!*(args[cur_arg + 1])) {
4614 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4615 file, linenum, args[0], args[1], ptr_arg);
4616 err_code |= ERR_ALERT | ERR_FATAL;
4617 goto out;
4618 }
4619 struct tcpcheck_rule *tcpcheck;
4620
4621 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4622
4623 tcpcheck->action = TCPCHK_ACT_EXPECT;
4624 tcpcheck->string_len = 0;
4625 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004626 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4627 error = NULL;
4628 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4629 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4630 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4631 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
4634 }
4635 tcpcheck->inverse = inverse;
4636
4637 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4638 }
4639 else {
4640 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4641 file, linenum, args[0], args[1], ptr_arg);
4642 err_code |= ERR_ALERT | ERR_FATAL;
4643 goto out;
4644 }
4645 }
4646 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004647 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004648 err_code |= ERR_ALERT | ERR_FATAL;
4649 goto out;
4650 }
4651 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004652 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004653 if (curproxy == &defproxy) {
4654 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004655 err_code |= ERR_ALERT | ERR_FATAL;
4656 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004657 }
4658
Willy Tarreaub80c2302007-11-30 20:51:32 +01004659 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004660 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004661
4662 if (strcmp(args[1], "fail") == 0) {
4663 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004664 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004665 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4666 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004669 }
4670
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004671 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4672 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4673 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004674 err_code |= ERR_ALERT | ERR_FATAL;
4675 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004676 }
4677 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4678 }
4679 else {
4680 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004681 err_code |= ERR_ALERT | ERR_FATAL;
4682 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004683 }
4684 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004685#ifdef TPROXY
4686 else if (!strcmp(args[0], "transparent")) {
4687 /* enable transparent proxy connections */
4688 curproxy->options |= PR_O_TRANSP;
4689 }
4690#endif
4691 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004692 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004693 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004694
Willy Tarreaubaaee002006-06-26 02:48:02 +02004695 if (*(args[1]) == 0) {
4696 Alert("parsing [%s:%d] : '%s' expects an integer argument.\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 }
4700 curproxy->maxconn = atol(args[1]);
4701 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004702 else if (!strcmp(args[0], "backlog")) { /* backlog */
4703 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004704 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004705
4706 if (*(args[1]) == 0) {
4707 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004708 err_code |= ERR_ALERT | ERR_FATAL;
4709 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004710 }
4711 curproxy->backlog = atol(args[1]);
4712 }
Willy Tarreau86034312006-12-29 00:10:33 +01004713 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004714 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004715 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004716
Willy Tarreau86034312006-12-29 00:10:33 +01004717 if (*(args[1]) == 0) {
4718 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004719 err_code |= ERR_ALERT | ERR_FATAL;
4720 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004721 }
4722 curproxy->fullconn = atol(args[1]);
4723 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004724 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4725 if (*(args[1]) == 0) {
4726 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004727 err_code |= ERR_ALERT | ERR_FATAL;
4728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004729 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004730 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4731 if (err) {
4732 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4733 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004734 err_code |= ERR_ALERT | ERR_FATAL;
4735 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004736 }
4737 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004738 }
4739 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004740 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004741 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004742 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004743
Willy Tarreaubaaee002006-06-26 02:48:02 +02004744 if (curproxy == &defproxy) {
4745 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004746 err_code |= ERR_ALERT | ERR_FATAL;
4747 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004748 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004749 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004750 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004751
Willy Tarreau902636f2013-03-10 19:44:48 +01004752 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004753 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004754 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004755 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004756 goto out;
4757 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004758
4759 proto = protocol_by_family(sk->ss_family);
4760 if (!proto || !proto->connect) {
4761 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4762 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004763 err_code |= ERR_ALERT | ERR_FATAL;
4764 goto out;
4765 }
4766
4767 if (port1 != port2) {
4768 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4769 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004770 err_code |= ERR_ALERT | ERR_FATAL;
4771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004772 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004773
4774 if (!port1) {
4775 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4776 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004777 err_code |= ERR_ALERT | ERR_FATAL;
4778 goto out;
4779 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004780
Willy Tarreaud5191e72010-02-09 20:50:45 +01004781 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004782 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004783 }
4784 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004785 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004786 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004787
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004788 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4789 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004790 err_code |= ERR_ALERT | ERR_FATAL;
4791 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004792 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004793 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004794 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004795 /**
4796 * The syntax for hash-type config element is
4797 * hash-type {map-based|consistent} [[<algo>] avalanche]
4798 *
4799 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4800 */
4801 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004802
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004803 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4804 err_code |= ERR_WARN;
4805
4806 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004807 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4808 }
4809 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004810 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4811 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004812 else if (strcmp(args[1], "avalanche") == 0) {
4813 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]);
4814 err_code |= ERR_ALERT | ERR_FATAL;
4815 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004816 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004817 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004818 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004819 err_code |= ERR_ALERT | ERR_FATAL;
4820 goto out;
4821 }
Bhaskar98634f02013-10-29 23:30:51 -04004822
4823 /* set the hash function to use */
4824 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004825 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004826 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004827
4828 /* if consistent with no argument, then avalanche modifier is also applied */
4829 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4830 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004831 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004832 /* set the hash function */
4833 if (!strcmp(args[2], "sdbm")) {
4834 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4835 }
4836 else if (!strcmp(args[2], "djb2")) {
4837 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01004838 }
4839 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004840 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004841 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01004842 else if (!strcmp(args[2], "crc32")) {
4843 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
4844 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004845 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01004846 Alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2', 'crc32', or 'wt6' hash functions.\n", file, linenum, args[0]);
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004847 err_code |= ERR_ALERT | ERR_FATAL;
4848 goto out;
4849 }
4850
4851 /* set the hash modifier */
4852 if (!strcmp(args[3], "avalanche")) {
4853 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4854 }
4855 else if (*args[3]) {
4856 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4857 err_code |= ERR_ALERT | ERR_FATAL;
4858 goto out;
4859 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004860 }
William Lallemanda73203e2012-03-12 12:48:57 +01004861 }
William Lallemanda73203e2012-03-12 12:48:57 +01004862 else if (strcmp(args[0], "unique-id-format") == 0) {
4863 if (!*(args[1])) {
4864 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4865 err_code |= ERR_ALERT | ERR_FATAL;
4866 goto out;
4867 }
William Lallemand3203ff42012-11-11 17:30:56 +01004868 if (*(args[2])) {
4869 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
4872 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004873 free(curproxy->conf.uniqueid_format_string);
4874 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004875
Willy Tarreau62a61232013-04-12 18:13:46 +02004876 free(curproxy->conf.uif_file);
4877 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4878 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004879 }
William Lallemanda73203e2012-03-12 12:48:57 +01004880
4881 else if (strcmp(args[0], "unique-id-header") == 0) {
4882 if (!*(args[1])) {
4883 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4884 err_code |= ERR_ALERT | ERR_FATAL;
4885 goto out;
4886 }
4887 free(curproxy->header_unique_id);
4888 curproxy->header_unique_id = strdup(args[1]);
4889 }
4890
William Lallemand723b73a2012-02-08 16:37:49 +01004891 else if (strcmp(args[0], "log-format") == 0) {
4892 if (!*(args[1])) {
4893 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4894 err_code |= ERR_ALERT | ERR_FATAL;
4895 goto out;
4896 }
William Lallemand3203ff42012-11-11 17:30:56 +01004897 if (*(args[2])) {
4898 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4899 err_code |= ERR_ALERT | ERR_FATAL;
4900 goto out;
4901 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004902
Willy Tarreau62a61232013-04-12 18:13:46 +02004903 if (curproxy->conf.logformat_string != default_http_log_format &&
4904 curproxy->conf.logformat_string != default_tcp_log_format &&
4905 curproxy->conf.logformat_string != clf_http_log_format)
4906 free(curproxy->conf.logformat_string);
4907 curproxy->conf.logformat_string = strdup(args[1]);
4908
4909 free(curproxy->conf.lfs_file);
4910 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4911 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004912
4913 /* get a chance to improve log-format error reporting by
4914 * reporting the correct line-number when possible.
4915 */
4916 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4917 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4918 file, linenum, curproxy->id);
4919 err_code |= ERR_WARN;
4920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004921 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01004922 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
4923 if (*(args[1]) == 0) {
4924 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
4925 err_code |= ERR_ALERT | ERR_FATAL;
4926 goto out;
4927 }
4928 free(curproxy->log_tag);
4929 curproxy->log_tag = strdup(args[1]);
4930 }
William Lallemand0f99e342011-10-12 17:50:54 +02004931 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4932 /* delete previous herited or defined syslog servers */
4933 struct logsrv *back;
4934
4935 if (*(args[1]) != 0) {
4936 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4937 err_code |= ERR_ALERT | ERR_FATAL;
4938 goto out;
4939 }
4940
William Lallemand723b73a2012-02-08 16:37:49 +01004941 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4942 LIST_DEL(&tmplogsrv->list);
4943 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004944 }
4945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004946 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004947 struct logsrv *logsrv;
4948
Willy Tarreaubaaee002006-06-26 02:48:02 +02004949 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004950 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004951 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004952 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004953 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004954 LIST_INIT(&node->list);
4955 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4956 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004957 }
4958 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004959 struct sockaddr_storage *sk;
4960 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02004961 int arg = 0;
4962 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004963
4964 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965
Willy Tarreau18324f52014-06-27 18:10:07 +02004966 /* just after the address, a length may be specified */
4967 if (strcmp(args[arg+2], "len") == 0) {
4968 len = atoi(args[arg+3]);
4969 if (len < 80 || len > 65535) {
4970 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4971 file, linenum, args[arg+3]);
4972 err_code |= ERR_ALERT | ERR_FATAL;
4973 goto out;
4974 }
4975 logsrv->maxlen = len;
4976
4977 /* skip these two args */
4978 arg += 2;
4979 }
4980 else
4981 logsrv->maxlen = MAX_SYSLOG_LEN;
4982
4983 if (logsrv->maxlen > global.max_syslog_len) {
4984 global.max_syslog_len = logsrv->maxlen;
4985 logline = realloc(logline, global.max_syslog_len + 1);
4986 }
4987
4988 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004989 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004990 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004991 err_code |= ERR_ALERT | ERR_FATAL;
4992 goto out;
4993
Willy Tarreaubaaee002006-06-26 02:48:02 +02004994 }
4995
William Lallemand0f99e342011-10-12 17:50:54 +02004996 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02004997 if (*(args[arg+3])) {
4998 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004999 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005000 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005001 err_code |= ERR_ALERT | ERR_FATAL;
5002 goto out;
5003
Willy Tarreaubaaee002006-06-26 02:48:02 +02005004 }
5005 }
5006
William Lallemand0f99e342011-10-12 17:50:54 +02005007 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005008 if (*(args[arg+4])) {
5009 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005010 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005011 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005012 err_code |= ERR_ALERT | ERR_FATAL;
5013 goto out;
5014
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005015 }
5016 }
5017
Willy Tarreau902636f2013-03-10 19:44:48 +01005018 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005019 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005020 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005021 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005022 goto out;
5023 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005024
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005025 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005026
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005027 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005028 if (port1 != port2) {
5029 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5030 file, linenum, args[0], args[1]);
5031 err_code |= ERR_ALERT | ERR_FATAL;
5032 goto out;
5033 }
5034
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005035 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005036 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005037 }
William Lallemand0f99e342011-10-12 17:50:54 +02005038
5039 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005040 }
5041 else {
5042 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5043 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005044 err_code |= ERR_ALERT | ERR_FATAL;
5045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005046 }
5047 }
5048 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005049 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005050 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005051 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005052 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005053
Willy Tarreau977b8e42006-12-29 14:19:17 +01005054 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005055 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005056
Willy Tarreaubaaee002006-06-26 02:48:02 +02005057 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005058 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5059 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005060 err_code |= ERR_ALERT | ERR_FATAL;
5061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005062 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005063
5064 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005065 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5066 free(curproxy->conn_src.iface_name);
5067 curproxy->conn_src.iface_name = NULL;
5068 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005069
Willy Tarreau902636f2013-03-10 19:44:48 +01005070 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005071 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005072 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005073 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005074 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005075 goto out;
5076 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005077
5078 proto = protocol_by_family(sk->ss_family);
5079 if (!proto || !proto->connect) {
5080 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005081 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005082 err_code |= ERR_ALERT | ERR_FATAL;
5083 goto out;
5084 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005085
5086 if (port1 != port2) {
5087 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5088 file, linenum, args[0], args[1]);
5089 err_code |= ERR_ALERT | ERR_FATAL;
5090 goto out;
5091 }
5092
Willy Tarreauef9a3602012-12-08 22:29:20 +01005093 curproxy->conn_src.source_addr = *sk;
5094 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005095
5096 cur_arg = 2;
5097 while (*(args[cur_arg])) {
5098 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005099#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5100#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005101 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005102 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5103 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005104 err_code |= ERR_ALERT | ERR_FATAL;
5105 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005106 }
5107#endif
5108 if (!*args[cur_arg + 1]) {
5109 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5110 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005111 err_code |= ERR_ALERT | ERR_FATAL;
5112 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005113 }
5114
5115 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005116 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5117 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005118 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005119 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5120 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005121 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5122 char *name, *end;
5123
5124 name = args[cur_arg+1] + 7;
5125 while (isspace(*name))
5126 name++;
5127
5128 end = name;
5129 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5130 end++;
5131
Willy Tarreauef9a3602012-12-08 22:29:20 +01005132 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5133 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5134 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5135 curproxy->conn_src.bind_hdr_len = end - name;
5136 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5137 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5138 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005139
5140 /* now look for an occurrence number */
5141 while (isspace(*end))
5142 end++;
5143 if (*end == ',') {
5144 end++;
5145 name = end;
5146 if (*end == '-')
5147 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005148 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005149 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005150 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005151 }
5152
Willy Tarreauef9a3602012-12-08 22:29:20 +01005153 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005154 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5155 " occurrences values smaller than %d.\n",
5156 file, linenum, MAX_HDR_HISTORY);
5157 err_code |= ERR_ALERT | ERR_FATAL;
5158 goto out;
5159 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005160 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005161 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005162
Willy Tarreau902636f2013-03-10 19:44:48 +01005163 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005164 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005165 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005166 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005167 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005168 goto out;
5169 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005170
5171 proto = protocol_by_family(sk->ss_family);
5172 if (!proto || !proto->connect) {
5173 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5174 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005175 err_code |= ERR_ALERT | ERR_FATAL;
5176 goto out;
5177 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005178
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005179 if (port1 != port2) {
5180 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5181 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005182 err_code |= ERR_ALERT | ERR_FATAL;
5183 goto out;
5184 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005185 curproxy->conn_src.tproxy_addr = *sk;
5186 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005187 }
5188 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005189#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005190 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005191#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005192#else /* no TPROXY support */
5193 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005194 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005195 err_code |= ERR_ALERT | ERR_FATAL;
5196 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005197#endif
5198 cur_arg += 2;
5199 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005200 }
5201
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005202 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5203#ifdef SO_BINDTODEVICE
5204 if (!*args[cur_arg + 1]) {
5205 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5206 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005207 err_code |= ERR_ALERT | ERR_FATAL;
5208 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005209 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005210 free(curproxy->conn_src.iface_name);
5211 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5212 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005213 global.last_checks |= LSTCHK_NETADM;
5214#else
5215 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5216 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005217 err_code |= ERR_ALERT | ERR_FATAL;
5218 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005219#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005220 cur_arg += 2;
5221 continue;
5222 }
5223 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005224 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005225 err_code |= ERR_ALERT | ERR_FATAL;
5226 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005228 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005229 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5230 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5231 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005232 err_code |= ERR_ALERT | ERR_FATAL;
5233 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005234 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005235 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005236 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005237 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5238 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005239 err_code |= ERR_ALERT | ERR_FATAL;
5240 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005241 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005242
5243 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005244 SMP_OPT_DIR_REQ, ACT_REPLACE, 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 Tarreaubaaee002006-06-26 02:48:02 +02005248 }
5249 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005250 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005251 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005252 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005253 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005255 }
5256 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005257 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005258 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005259 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005260 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005262 }
5263 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005264 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005265 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005266 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005267 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005268 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005269 }
5270 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005271 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005272 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005273 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005274 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005276 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005277 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005278 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005279 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005280 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005281 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005282 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005283 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005284 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005285 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005286 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005287 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005288 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005289 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005290
5291 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5292 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 +01005293 }
5294 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005295 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005296 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005297 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005298 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005299 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005300
5301 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5302 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 +01005303 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005305 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5307 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005308 err_code |= ERR_ALERT | ERR_FATAL;
5309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005311
5312 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005313 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005314 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005315 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005316 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005317 }
5318 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005319 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005320 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005321 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005322 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005324 }
5325 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005326 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005327 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005328 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005329 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005330 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005331 }
5332 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005333 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005334 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005335 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005336 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005337 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005338 }
5339 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005340 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005341 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005342 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005343 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005345 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005346 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005347 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005348 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005349 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005350 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005351 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005352 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005353 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005354 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005355
Willy Tarreaubaaee002006-06-26 02:48:02 +02005356 if (curproxy == &defproxy) {
5357 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005358 err_code |= ERR_ALERT | ERR_FATAL;
5359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005361 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005362 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005363
Willy Tarreaubaaee002006-06-26 02:48:02 +02005364 if (*(args[1]) == 0) {
5365 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005366 err_code |= ERR_ALERT | ERR_FATAL;
5367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005368 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005369
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005370 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005371 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5372 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5373 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005374 err_code |= ERR_ALERT | ERR_FATAL;
5375 goto out;
5376 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005377 err_code |= warnif_cond_conflicts(cond,
5378 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5379 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005380 }
5381 else if (*args[2]) {
5382 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5383 file, linenum, args[0], args[2]);
5384 err_code |= ERR_ALERT | ERR_FATAL;
5385 goto out;
5386 }
5387
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005388 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005389 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005390 wl->s = strdup(args[1]);
5391 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005392 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005393 }
5394 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005395 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005396 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5397 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005398 err_code |= ERR_ALERT | ERR_FATAL;
5399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005400 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005401
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_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005404 args[0], args[1], args[2], (const char **)args+3);
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], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005409 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005410 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005411 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005412 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005414 }
5415 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005416 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005417 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005418 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005419 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005421 }
5422 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005423 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005424 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5425 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005426 err_code |= ERR_ALERT | ERR_FATAL;
5427 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005428 }
5429
Willy Tarreauade5ec42010-01-28 19:33:49 +01005430 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005431 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005432 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005433 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005435 }
5436 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005437 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005438 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005439 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005440 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005442 }
5443 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005444 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005445 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005446 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005447 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005448 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005449 }
5450 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005451 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005452
Willy Tarreaubaaee002006-06-26 02:48:02 +02005453 if (curproxy == &defproxy) {
5454 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005455 err_code |= ERR_ALERT | ERR_FATAL;
5456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005457 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005458 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005459 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005460
Willy Tarreaubaaee002006-06-26 02:48:02 +02005461 if (*(args[1]) == 0) {
5462 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005463 err_code |= ERR_ALERT | ERR_FATAL;
5464 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005465 }
5466
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005467 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005468 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5469 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5470 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005471 err_code |= ERR_ALERT | ERR_FATAL;
5472 goto out;
5473 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005474 err_code |= warnif_cond_conflicts(cond,
5475 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5476 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005477 }
5478 else if (*args[2]) {
5479 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5480 file, linenum, args[0], args[2]);
5481 err_code |= ERR_ALERT | ERR_FATAL;
5482 goto out;
5483 }
5484
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005485 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005486 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005487 wl->s = strdup(args[1]);
5488 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005489 }
5490 else if (!strcmp(args[0], "errorloc") ||
5491 !strcmp(args[0], "errorloc302") ||
5492 !strcmp(args[0], "errorloc303")) { /* error location */
5493 int errnum, errlen;
5494 char *err;
5495
Willy Tarreau977b8e42006-12-29 14:19:17 +01005496 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005497 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005498
Willy Tarreaubaaee002006-06-26 02:48:02 +02005499 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005500 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005501 err_code |= ERR_ALERT | ERR_FATAL;
5502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005503 }
5504
5505 errnum = atol(args[1]);
5506 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005507 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5508 err = malloc(errlen);
5509 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005510 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005511 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5512 err = malloc(errlen);
5513 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005514 }
5515
Willy Tarreau0f772532006-12-23 20:51:41 +01005516 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5517 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005518 chunk_destroy(&curproxy->errmsg[rc]);
5519 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005520 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005521 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005522 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005523
5524 if (rc >= HTTP_ERR_SIZE) {
5525 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5526 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005527 free(err);
5528 }
5529 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005530 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5531 int errnum, errlen, fd;
5532 char *err;
5533 struct stat stat;
5534
5535 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005536 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005537
5538 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005539 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005540 err_code |= ERR_ALERT | ERR_FATAL;
5541 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005542 }
5543
5544 fd = open(args[2], O_RDONLY);
5545 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5546 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5547 file, linenum, args[2], args[1]);
5548 if (fd >= 0)
5549 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005550 err_code |= ERR_ALERT | ERR_FATAL;
5551 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005552 }
5553
Willy Tarreau27a674e2009-08-17 07:23:33 +02005554 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005555 errlen = stat.st_size;
5556 } else {
5557 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005558 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005559 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005560 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005561 }
5562
5563 err = malloc(errlen); /* malloc() must succeed during parsing */
5564 errnum = read(fd, err, errlen);
5565 if (errnum != errlen) {
5566 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5567 file, linenum, args[2], args[1]);
5568 close(fd);
5569 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005570 err_code |= ERR_ALERT | ERR_FATAL;
5571 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005572 }
5573 close(fd);
5574
5575 errnum = atol(args[1]);
5576 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5577 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005578 chunk_destroy(&curproxy->errmsg[rc]);
5579 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005580 break;
5581 }
5582 }
5583
5584 if (rc >= HTTP_ERR_SIZE) {
5585 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5586 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005587 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005588 free(err);
5589 }
5590 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005591 else if (!strcmp(args[0], "compression")) {
5592 struct comp *comp;
5593 if (curproxy->comp == NULL) {
5594 comp = calloc(1, sizeof(struct comp));
5595 curproxy->comp = comp;
5596 } else {
5597 comp = curproxy->comp;
5598 }
5599
5600 if (!strcmp(args[1], "algo")) {
5601 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005602 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005603
William Lallemand82fe75c2012-10-23 10:25:10 +02005604 cur_arg = 2;
5605 if (!*args[cur_arg]) {
5606 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5607 file, linenum, args[0]);
5608 err_code |= ERR_ALERT | ERR_FATAL;
5609 goto out;
5610 }
5611 while (*(args[cur_arg])) {
5612 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5613 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5614 file, linenum, args[0], args[cur_arg]);
5615 err_code |= ERR_ALERT | ERR_FATAL;
5616 goto out;
5617 }
William Lallemand552df672012-11-07 13:21:47 +01005618 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5619 curproxy->comp->algos->end(&ctx);
5620 } else {
5621 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5622 file, linenum, args[0], args[cur_arg]);
5623 err_code |= ERR_ALERT | ERR_FATAL;
5624 goto out;
5625 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005626 cur_arg ++;
5627 continue;
5628 }
5629 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005630 else if (!strcmp(args[1], "offload")) {
5631 comp->offload = 1;
5632 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005633 else if (!strcmp(args[1], "type")) {
5634 int cur_arg;
5635 cur_arg = 2;
5636 if (!*args[cur_arg]) {
5637 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5638 file, linenum, args[0]);
5639 err_code |= ERR_ALERT | ERR_FATAL;
5640 goto out;
5641 }
5642 while (*(args[cur_arg])) {
5643 comp_append_type(comp, args[cur_arg]);
5644 cur_arg ++;
5645 continue;
5646 }
5647 }
5648 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005649 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005650 file, linenum, args[0]);
5651 err_code |= ERR_ALERT | ERR_FATAL;
5652 goto out;
5653 }
5654 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005655 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005656 struct cfg_kw_list *kwl;
5657 int index;
5658
5659 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5660 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5661 if (kwl->kw[index].section != CFG_LISTEN)
5662 continue;
5663 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5664 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005665 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005666 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005667 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005668 err_code |= ERR_ALERT | ERR_FATAL;
5669 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005670 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005671 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005672 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005673 err_code |= ERR_WARN;
5674 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005675 }
Willy Tarreau93893792009-07-23 13:19:11 +02005676 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005677 }
5678 }
5679 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005680
Willy Tarreau6daf3432008-01-22 16:44:08 +01005681 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005682 err_code |= ERR_ALERT | ERR_FATAL;
5683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005684 }
Willy Tarreau93893792009-07-23 13:19:11 +02005685 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005686 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005687 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005688}
5689
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005690int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005691cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
5692{
5693#ifdef CONFIG_HAP_NS
5694 const char *err;
5695 const char *item = args[0];
5696
5697 if (!strcmp(item, "namespace_list")) {
5698 return 0;
5699 }
5700 else if (!strcmp(item, "namespace")) {
5701 size_t idx = 1;
5702 const char *current;
5703 while (*(current = args[idx++])) {
5704 err = invalid_char(current);
5705 if (err) {
5706 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5707 file, linenum, *err, item, current);
5708 return ERR_ALERT | ERR_FATAL;
5709 }
5710
5711 if (netns_store_lookup(current, strlen(current))) {
5712 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
5713 file, linenum, current);
5714 return ERR_ALERT | ERR_FATAL;
5715 }
5716 if (!netns_store_insert(current)) {
5717 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
5718 file, linenum, current);
5719 return ERR_ALERT | ERR_FATAL;
5720 }
5721 }
5722 }
5723
5724 return 0;
5725#else
5726 Alert("parsing [%s:%d]: namespace support is not compiled in.",
5727 file, linenum);
5728 return ERR_ALERT | ERR_FATAL;
5729#endif
5730}
5731
5732int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005733cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5734{
5735
5736 int err_code = 0;
5737 const char *err;
5738
5739 if (!strcmp(args[0], "userlist")) { /* new userlist */
5740 struct userlist *newul;
5741
5742 if (!*args[1]) {
5743 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5744 file, linenum, args[0]);
5745 err_code |= ERR_ALERT | ERR_FATAL;
5746 goto out;
5747 }
5748
5749 err = invalid_char(args[1]);
5750 if (err) {
5751 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5752 file, linenum, *err, args[0], args[1]);
5753 err_code |= ERR_ALERT | ERR_FATAL;
5754 goto out;
5755 }
5756
5757 for (newul = userlist; newul; newul = newul->next)
5758 if (!strcmp(newul->name, args[1])) {
5759 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5760 file, linenum, args[1]);
5761 err_code |= ERR_WARN;
5762 goto out;
5763 }
5764
5765 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5766 if (!newul) {
5767 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5768 err_code |= ERR_ALERT | ERR_ABORT;
5769 goto out;
5770 }
5771
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005772 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005773 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005774 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5775 err_code |= ERR_ALERT | ERR_ABORT;
5776 goto out;
5777 }
5778
5779 newul->next = userlist;
5780 userlist = newul;
5781
5782 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005783 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005784 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005785 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005786
5787 if (!*args[1]) {
5788 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5789 file, linenum, args[0]);
5790 err_code |= ERR_ALERT | ERR_FATAL;
5791 goto out;
5792 }
5793
5794 err = invalid_char(args[1]);
5795 if (err) {
5796 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5797 file, linenum, *err, args[0], args[1]);
5798 err_code |= ERR_ALERT | ERR_FATAL;
5799 goto out;
5800 }
5801
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005802 for (ag = userlist->groups; ag; ag = ag->next)
5803 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005804 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5805 file, linenum, args[1], userlist->name);
5806 err_code |= ERR_ALERT;
5807 goto out;
5808 }
5809
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005810 ag = calloc(1, sizeof(*ag));
5811 if (!ag) {
5812 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5813 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005814 goto out;
5815 }
5816
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005817 ag->name = strdup(args[1]);
5818 if (!ag) {
5819 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5820 err_code |= ERR_ALERT | ERR_ABORT;
5821 goto out;
5822 }
5823
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005824 cur_arg = 2;
5825
5826 while (*args[cur_arg]) {
5827 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005828 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005829 cur_arg += 2;
5830 continue;
5831 } else {
5832 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5833 file, linenum, args[0]);
5834 err_code |= ERR_ALERT | ERR_FATAL;
5835 goto out;
5836 }
5837 }
5838
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005839 ag->next = userlist->groups;
5840 userlist->groups = ag;
5841
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005842 } else if (!strcmp(args[0], "user")) { /* new user */
5843 struct auth_users *newuser;
5844 int cur_arg;
5845
5846 if (!*args[1]) {
5847 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5848 file, linenum, args[0]);
5849 err_code |= ERR_ALERT | ERR_FATAL;
5850 goto out;
5851 }
5852
5853 for (newuser = userlist->users; newuser; newuser = newuser->next)
5854 if (!strcmp(newuser->user, args[1])) {
5855 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5856 file, linenum, args[1], userlist->name);
5857 err_code |= ERR_ALERT;
5858 goto out;
5859 }
5860
5861 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5862 if (!newuser) {
5863 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5864 err_code |= ERR_ALERT | ERR_ABORT;
5865 goto out;
5866 }
5867
5868 newuser->user = strdup(args[1]);
5869
5870 newuser->next = userlist->users;
5871 userlist->users = newuser;
5872
5873 cur_arg = 2;
5874
5875 while (*args[cur_arg]) {
5876 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02005877#ifdef CONFIG_HAP_CRYPT
5878 if (!crypt("", args[cur_arg + 1])) {
5879 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
5880 file, linenum, newuser->user);
5881 err_code |= ERR_ALERT | ERR_FATAL;
5882 goto out;
5883 }
5884#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005885 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5886 file, linenum);
5887 err_code |= ERR_ALERT;
5888#endif
5889 newuser->pass = strdup(args[cur_arg + 1]);
5890 cur_arg += 2;
5891 continue;
5892 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5893 newuser->pass = strdup(args[cur_arg + 1]);
5894 newuser->flags |= AU_O_INSECURE;
5895 cur_arg += 2;
5896 continue;
5897 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005898 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005899 cur_arg += 2;
5900 continue;
5901 } else {
5902 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5903 file, linenum, args[0]);
5904 err_code |= ERR_ALERT | ERR_FATAL;
5905 goto out;
5906 }
5907 }
5908 } else {
5909 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5910 err_code |= ERR_ALERT | ERR_FATAL;
5911 }
5912
5913out:
5914 return err_code;
5915}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005916
5917/*
5918 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005919 * Returns the error code, 0 if OK, or any combination of :
5920 * - ERR_ABORT: must abort ASAP
5921 * - ERR_FATAL: we can continue parsing but not start the service
5922 * - ERR_WARN: a warning has been emitted
5923 * - ERR_ALERT: an alert has been emitted
5924 * Only the two first ones can stop processing, the two others are just
5925 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005926 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005927int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005928{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005929 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005930 FILE *f;
5931 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005932 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005933 struct cfg_section *cs = NULL;
5934 struct cfg_section *ics;
5935
5936 /* Register internal sections */
5937 if (!cfg_register_section("listen", cfg_parse_listen) ||
5938 !cfg_register_section("frontend", cfg_parse_listen) ||
5939 !cfg_register_section("backend", cfg_parse_listen) ||
5940 !cfg_register_section("ruleset", cfg_parse_listen) ||
5941 !cfg_register_section("defaults", cfg_parse_listen) ||
5942 !cfg_register_section("global", cfg_parse_global) ||
5943 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005944 !cfg_register_section("peers", cfg_parse_peers) ||
5945 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005946 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005947
Willy Tarreaubaaee002006-06-26 02:48:02 +02005948 if ((f=fopen(file,"r")) == NULL)
5949 return -1;
5950
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005951 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005952 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005953 char *end;
5954 char *args[MAX_LINE_ARGS + 1];
5955 char *line = thisline;
5956
Willy Tarreaubaaee002006-06-26 02:48:02 +02005957 linenum++;
5958
5959 end = line + strlen(line);
5960
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005961 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5962 /* Check if we reached the limit and the last char is not \n.
5963 * Watch out for the last line without the terminating '\n'!
5964 */
5965 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005966 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005967 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005968 }
5969
Willy Tarreaubaaee002006-06-26 02:48:02 +02005970 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005971 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005972 line++;
5973
5974 arg = 0;
5975 args[arg] = line;
5976
5977 while (*line && arg < MAX_LINE_ARGS) {
5978 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5979 * C equivalent value. Other combinations left unchanged (eg: \1).
5980 */
5981 if (*line == '\\') {
5982 int skip = 0;
5983 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5984 *line = line[1];
5985 skip = 1;
5986 }
5987 else if (line[1] == 'r') {
5988 *line = '\r';
5989 skip = 1;
5990 }
5991 else if (line[1] == 'n') {
5992 *line = '\n';
5993 skip = 1;
5994 }
5995 else if (line[1] == 't') {
5996 *line = '\t';
5997 skip = 1;
5998 }
5999 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006000 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006001 unsigned char hex1, hex2;
6002 hex1 = toupper(line[2]) - '0';
6003 hex2 = toupper(line[3]) - '0';
6004 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6005 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6006 *line = (hex1<<4) + hex2;
6007 skip = 3;
6008 }
6009 else {
6010 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006011 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006012 }
6013 }
6014 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006015 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006016 end -= skip;
6017 }
6018 line++;
6019 }
6020 else if (*line == '#' || *line == '\n' || *line == '\r') {
6021 /* end of string, end of loop */
6022 *line = 0;
6023 break;
6024 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006025 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006026 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006027 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006028 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006029 line++;
6030 args[++arg] = line;
6031 }
6032 else {
6033 line++;
6034 }
6035 }
6036
6037 /* empty line */
6038 if (!**args)
6039 continue;
6040
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006041 if (*line) {
6042 /* we had to stop due to too many args.
6043 * Let's terminate the string, print the offending part then cut the
6044 * last arg.
6045 */
6046 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6047 line++;
6048 *line = '\0';
6049
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006050 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006051 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006052 err_code |= ERR_ALERT | ERR_FATAL;
6053 args[arg] = line;
6054 }
6055
Willy Tarreau540abe42007-05-02 20:50:16 +02006056 /* zero out remaining args and ensure that at least one entry
6057 * is zeroed out.
6058 */
6059 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006060 args[arg] = line;
6061 }
6062
Willy Tarreau3842f002009-06-14 11:39:52 +02006063 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006064 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006065 char *tmp;
6066
Willy Tarreau3842f002009-06-14 11:39:52 +02006067 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006068 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006069 for (arg=0; *args[arg+1]; arg++)
6070 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006071 *tmp = '\0'; // fix the next arg to \0
6072 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006073 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006074 else if (!strcmp(args[0], "default")) {
6075 kwm = KWM_DEF;
6076 for (arg=0; *args[arg+1]; arg++)
6077 args[arg] = args[arg+1]; // shift args after inversion
6078 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006079
William Lallemand0f99e342011-10-12 17:50:54 +02006080 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6081 strcmp(args[0], "log") != 0) {
6082 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006083 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006084 }
6085
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006086 /* detect section start */
6087 list_for_each_entry(ics, &sections, list) {
6088 if (strcmp(args[0], ics->section_name) == 0) {
6089 cursection = ics->section_name;
6090 cs = ics;
6091 break;
6092 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006093 }
6094
Willy Tarreaubaaee002006-06-26 02:48:02 +02006095 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006096 if (cs)
6097 err_code |= cs->section_parser(file, linenum, args, kwm);
6098 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006099 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006100 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006101 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006102
6103 if (err_code & ERR_ABORT)
6104 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006105 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006106 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006107 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006108 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006109}
6110
Willy Tarreau64ab6072014-09-16 12:17:36 +02006111/* This function propagates processes from frontend <from> to backend <to> so
6112 * that it is always guaranteed that a backend pointed to by a frontend is
6113 * bound to all of its processes. After that, if the target is a "listen"
6114 * instance, the function recursively descends the target's own targets along
6115 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6116 * checked first to ensure that <to> is already bound to all processes of
6117 * <from>, there is no risk of looping and we ensure to follow the shortest
6118 * path to the destination.
6119 *
6120 * It is possible to set <to> to NULL for the first call so that the function
6121 * takes care of visiting the initial frontend in <from>.
6122 *
6123 * It is important to note that the function relies on the fact that all names
6124 * have already been resolved.
6125 */
6126void propagate_processes(struct proxy *from, struct proxy *to)
6127{
6128 struct switching_rule *rule;
6129 struct hdr_exp *exp;
6130
6131 if (to) {
6132 /* check whether we need to go down */
6133 if (from->bind_proc &&
6134 (from->bind_proc & to->bind_proc) == from->bind_proc)
6135 return;
6136
6137 if (!from->bind_proc && !to->bind_proc)
6138 return;
6139
6140 to->bind_proc = from->bind_proc ?
6141 (to->bind_proc | from->bind_proc) : 0;
6142
6143 /* now propagate down */
6144 from = to;
6145 }
6146
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006147 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006148 return;
6149
Willy Tarreauf6b70012014-12-18 14:00:43 +01006150 if (from->state == PR_STSTOPPED)
6151 return;
6152
Willy Tarreau64ab6072014-09-16 12:17:36 +02006153 /* default_backend */
6154 if (from->defbe.be)
6155 propagate_processes(from, from->defbe.be);
6156
6157 /* use_backend */
6158 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006159 if (rule->dynamic)
6160 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006161 to = rule->be.backend;
6162 propagate_processes(from, to);
6163 }
6164
6165 /* reqsetbe */
6166 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6167 if (exp->action != ACT_SETBE)
6168 continue;
6169 to = (struct proxy *)exp->replace;
6170 propagate_processes(from, to);
6171 }
6172}
6173
Willy Tarreaubb925012009-07-23 13:36:36 +02006174/*
6175 * Returns the error code, 0 if OK, or any combination of :
6176 * - ERR_ABORT: must abort ASAP
6177 * - ERR_FATAL: we can continue parsing but not start the service
6178 * - ERR_WARN: a warning has been emitted
6179 * - ERR_ALERT: an alert has been emitted
6180 * Only the two first ones can stop processing, the two others are just
6181 * indicators.
6182 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006183int check_config_validity()
6184{
6185 int cfgerr = 0;
6186 struct proxy *curproxy = NULL;
6187 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006188 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006189 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006190 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006191
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006192 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006193 /*
6194 * Now, check for the integrity of all that we have collected.
6195 */
6196
6197 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006198 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006199
Willy Tarreau193b8c62012-11-22 00:17:38 +01006200 if (!global.tune.max_http_hdr)
6201 global.tune.max_http_hdr = MAX_HTTP_HDR;
6202
6203 if (!global.tune.cookie_len)
6204 global.tune.cookie_len = CAPTURE_LEN;
6205
6206 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6207
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006208 /* Post initialisation of the users and groups lists. */
6209 err_code = userlist_postinit();
6210 if (err_code != ERR_NONE)
6211 goto out;
6212
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006213 /* first, we will invert the proxy list order */
6214 curproxy = NULL;
6215 while (proxy) {
6216 struct proxy *next;
6217
6218 next = proxy->next;
6219 proxy->next = curproxy;
6220 curproxy = proxy;
6221 if (!next)
6222 break;
6223 proxy = next;
6224 }
6225
Willy Tarreau419ead82014-09-16 13:41:21 +02006226 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006227 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006228 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006229 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006230 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006231 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006232 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006233 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006234
Willy Tarreau050536d2012-10-04 08:47:34 +02006235 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006236 /* proxy ID not set, use automatic numbering with first
6237 * spare entry starting with next_pxid.
6238 */
6239 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6240 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6241 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006242 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006243 next_pxid++;
6244
Willy Tarreau55ea7572007-06-17 19:56:27 +02006245
Willy Tarreaubaaee002006-06-26 02:48:02 +02006246 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006247 /* ensure we don't keep listeners uselessly bound */
6248 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006249 continue;
6250 }
6251
Willy Tarreau102df612014-05-07 23:56:38 +02006252 /* Check multi-process mode compatibility for the current proxy */
6253
6254 if (curproxy->bind_proc) {
6255 /* an explicit bind-process was specified, let's check how many
6256 * processes remain.
6257 */
6258 nbproc = popcount(curproxy->bind_proc);
6259
6260 curproxy->bind_proc &= nbits(global.nbproc);
6261 if (!curproxy->bind_proc && nbproc == 1) {
6262 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);
6263 curproxy->bind_proc = 1;
6264 }
6265 else if (!curproxy->bind_proc && nbproc > 1) {
6266 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);
6267 curproxy->bind_proc = 0;
6268 }
6269 }
6270
Willy Tarreau3d209582014-05-09 17:06:11 +02006271 /* check and reduce the bind-proc of each listener */
6272 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6273 unsigned long mask;
6274
6275 if (!bind_conf->bind_proc)
6276 continue;
6277
6278 mask = nbits(global.nbproc);
6279 if (curproxy->bind_proc)
6280 mask &= curproxy->bind_proc;
6281 /* mask cannot be null here thanks to the previous checks */
6282
6283 nbproc = popcount(bind_conf->bind_proc);
6284 bind_conf->bind_proc &= mask;
6285
6286 if (!bind_conf->bind_proc && nbproc == 1) {
6287 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",
6288 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6289 bind_conf->bind_proc = mask & ~(mask - 1);
6290 }
6291 else if (!bind_conf->bind_proc && nbproc > 1) {
6292 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",
6293 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6294 bind_conf->bind_proc = 0;
6295 }
6296 }
6297
Willy Tarreau102df612014-05-07 23:56:38 +02006298 if (global.nbproc > 1 && curproxy->table.peers.name) {
6299 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6300 curproxy->id);
6301 cfgerr++;
6302 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006303
Willy Tarreauff01a212009-03-15 13:46:16 +01006304 switch (curproxy->mode) {
6305 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006306 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006307 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006308 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6309 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006310 cfgerr++;
6311 }
6312
6313 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006314 Warning("config : servers will be ignored for %s '%s'.\n",
6315 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006316 break;
6317
6318 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006319 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006320 break;
6321
6322 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006323 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006324 break;
6325 }
6326
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006327 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006328 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006329 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006330 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6331 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006332 cfgerr++;
6333 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006334#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006335 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006336 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6337 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006338 cfgerr++;
6339 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006340#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006341 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006342 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6343 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006344 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006345 }
6346 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006347 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006348 /* If no LB algo is set in a backend, and we're not in
6349 * transparent mode, dispatch mode nor proxy mode, we
6350 * want to use balance roundrobin by default.
6351 */
6352 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6353 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006354 }
6355 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006356
Willy Tarreau1620ec32011-08-06 17:05:02 +02006357 if (curproxy->options & PR_O_DISPATCH)
6358 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6359 else if (curproxy->options & PR_O_HTTP_PROXY)
6360 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6361 else if (curproxy->options & PR_O_TRANSP)
6362 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006363
Willy Tarreau1620ec32011-08-06 17:05:02 +02006364 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6365 if (curproxy->options & PR_O_DISABLE404) {
6366 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6367 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6368 err_code |= ERR_WARN;
6369 curproxy->options &= ~PR_O_DISABLE404;
6370 }
6371 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6372 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6373 "send-state", proxy_type_str(curproxy), curproxy->id);
6374 err_code |= ERR_WARN;
6375 curproxy->options &= ~PR_O2_CHK_SNDST;
6376 }
Willy Tarreauef781042010-01-27 11:53:01 +01006377 }
6378
Simon Horman98637e52014-06-20 12:30:16 +09006379 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6380 if (!global.external_check) {
6381 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6382 curproxy->id, "option external-check");
6383 cfgerr++;
6384 }
6385 if (!curproxy->check_command) {
6386 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6387 curproxy->id, "option external-check");
6388 cfgerr++;
6389 }
6390 }
6391
6392 if (curproxy->check_command) {
6393 int clear = 0;
6394 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6395 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6396 "external-check command", proxy_type_str(curproxy), curproxy->id);
6397 err_code |= ERR_WARN;
6398 clear = 1;
6399 }
6400 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6401 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6402 curproxy->id, "external-check command");
6403 cfgerr++;
6404 }
6405 if (clear) {
6406 free(curproxy->check_command);
6407 curproxy->check_command = NULL;
6408 }
6409 }
6410
6411 if (curproxy->check_path) {
6412 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6413 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6414 "external-check path", proxy_type_str(curproxy), curproxy->id);
6415 err_code |= ERR_WARN;
6416 free(curproxy->check_path);
6417 curproxy->check_path = NULL;
6418 }
6419 }
6420
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006421 /* if a default backend was specified, let's find it */
6422 if (curproxy->defbe.name) {
6423 struct proxy *target;
6424
Alex Williams96532db2009-11-01 21:27:13 -05006425 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006426 if (!target) {
6427 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6428 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006429 cfgerr++;
6430 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006431 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6432 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006433 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006434 } else {
6435 free(curproxy->defbe.name);
6436 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006437
6438 /* Emit a warning if this proxy also has some servers */
6439 if (curproxy->srv) {
6440 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6441 curproxy->id);
6442 err_code |= ERR_WARN;
6443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006444 }
6445 }
6446
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006447 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006448 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6449 /* map jump target for ACT_SETBE in req_rep chain */
6450 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006451 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006452 struct proxy *target;
6453
Willy Tarreaua496b602006-12-17 23:15:24 +01006454 if (exp->action != ACT_SETBE)
6455 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006456
Alex Williams96532db2009-11-01 21:27:13 -05006457 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006458 if (!target) {
6459 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6460 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006461 cfgerr++;
6462 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006463 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6464 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006465 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006466 } else {
6467 free((void *)exp->replace);
6468 exp->replace = (const char *)target;
6469 }
6470 }
6471 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006472
6473 /* find the target proxy for 'use_backend' rules */
6474 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006475 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006476 struct logformat_node *node;
6477 char *pxname;
6478
6479 /* Try to parse the string as a log format expression. If the result
6480 * of the parsing is only one entry containing a simple string, then
6481 * it's a standard string corresponding to a static rule, thus the
6482 * parsing is cancelled and be.name is restored to be resolved.
6483 */
6484 pxname = rule->be.name;
6485 LIST_INIT(&rule->be.expr);
6486 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6487 curproxy->conf.args.file, curproxy->conf.args.line);
6488 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6489
6490 if (!LIST_ISEMPTY(&rule->be.expr)) {
6491 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6492 rule->dynamic = 1;
6493 free(pxname);
6494 continue;
6495 }
6496 /* simple string: free the expression and fall back to static rule */
6497 free(node->arg);
6498 free(node);
6499 }
6500
6501 rule->dynamic = 0;
6502 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006503
Alex Williams96532db2009-11-01 21:27:13 -05006504 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006505
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006506 if (!target) {
6507 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6508 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006509 cfgerr++;
6510 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006511 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6512 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006513 cfgerr++;
6514 } else {
6515 free((void *)rule->be.name);
6516 rule->be.backend = target;
6517 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006518 }
6519
Willy Tarreau64ab6072014-09-16 12:17:36 +02006520 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006521 list_for_each_entry(srule, &curproxy->server_rules, list) {
6522 struct server *target = findserver(curproxy, srule->srv.name);
6523
6524 if (!target) {
6525 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6526 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6527 cfgerr++;
6528 continue;
6529 }
6530 free((void *)srule->srv.name);
6531 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006532 }
6533
Emeric Brunb982a3d2010-01-04 15:45:53 +01006534 /* find the target table for 'stick' rules */
6535 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6536 struct proxy *target;
6537
Emeric Brun1d33b292010-01-04 15:47:17 +01006538 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6539 if (mrule->flags & STK_IS_STORE)
6540 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6541
Emeric Brunb982a3d2010-01-04 15:45:53 +01006542 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006543 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006544 else
6545 target = curproxy;
6546
6547 if (!target) {
6548 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6549 curproxy->id, mrule->table.name);
6550 cfgerr++;
6551 }
6552 else if (target->table.size == 0) {
6553 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6554 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6555 cfgerr++;
6556 }
Willy Tarreau12785782012-04-27 21:37:17 +02006557 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6558 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006559 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6560 cfgerr++;
6561 }
6562 else {
6563 free((void *)mrule->table.name);
6564 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006565 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006566 }
6567 }
6568
6569 /* find the target table for 'store response' rules */
6570 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6571 struct proxy *target;
6572
Emeric Brun1d33b292010-01-04 15:47:17 +01006573 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6574
Emeric Brunb982a3d2010-01-04 15:45:53 +01006575 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006576 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006577 else
6578 target = curproxy;
6579
6580 if (!target) {
6581 Alert("Proxy '%s': unable to find store table '%s'.\n",
6582 curproxy->id, mrule->table.name);
6583 cfgerr++;
6584 }
6585 else if (target->table.size == 0) {
6586 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6587 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6588 cfgerr++;
6589 }
Willy Tarreau12785782012-04-27 21:37:17 +02006590 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6591 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006592 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6593 cfgerr++;
6594 }
6595 else {
6596 free((void *)mrule->table.name);
6597 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006598 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006599 }
6600 }
6601
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006602 /* find the target table for 'tcp-request' layer 4 rules */
6603 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6604 struct proxy *target;
6605
Willy Tarreaub4c84932013-07-23 19:15:30 +02006606 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006607 continue;
6608
6609 if (trule->act_prm.trk_ctr.table.n)
6610 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6611 else
6612 target = curproxy;
6613
6614 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006615 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6616 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006617 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006618 cfgerr++;
6619 }
6620 else if (target->table.size == 0) {
6621 Alert("Proxy '%s': table '%s' used but not configured.\n",
6622 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6623 cfgerr++;
6624 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006625 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6626 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6627 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 +01006628 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006629 cfgerr++;
6630 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006631 else {
6632 free(trule->act_prm.trk_ctr.table.n);
6633 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006634 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006635 * to pass a list of counters to track and allocate them right here using
6636 * stktable_alloc_data_type().
6637 */
6638 }
6639 }
6640
Willy Tarreaud1f96522010-08-03 19:34:32 +02006641 /* find the target table for 'tcp-request' layer 6 rules */
6642 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6643 struct proxy *target;
6644
Willy Tarreaub4c84932013-07-23 19:15:30 +02006645 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006646 continue;
6647
6648 if (trule->act_prm.trk_ctr.table.n)
6649 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6650 else
6651 target = curproxy;
6652
6653 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006654 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6655 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006656 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006657 cfgerr++;
6658 }
6659 else if (target->table.size == 0) {
6660 Alert("Proxy '%s': table '%s' used but not configured.\n",
6661 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6662 cfgerr++;
6663 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006664 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6665 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6666 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 +01006667 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006668 cfgerr++;
6669 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006670 else {
6671 free(trule->act_prm.trk_ctr.table.n);
6672 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006673 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006674 * to pass a list of counters to track and allocate them right here using
6675 * stktable_alloc_data_type().
6676 */
6677 }
6678 }
6679
Willy Tarreau09448f72014-06-25 18:12:15 +02006680 /* find the target table for 'http-request' layer 7 rules */
6681 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6682 struct proxy *target;
6683
6684 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6685 continue;
6686
6687 if (hrqrule->act_prm.trk_ctr.table.n)
6688 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6689 else
6690 target = curproxy;
6691
6692 if (!target) {
6693 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6694 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6695 http_req_trk_idx(hrqrule->action));
6696 cfgerr++;
6697 }
6698 else if (target->table.size == 0) {
6699 Alert("Proxy '%s': table '%s' used but not configured.\n",
6700 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6701 cfgerr++;
6702 }
6703 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6704 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6705 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6706 http_req_trk_idx(hrqrule->action));
6707 cfgerr++;
6708 }
6709 else {
6710 free(hrqrule->act_prm.trk_ctr.table.n);
6711 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6712 /* Note: if we decide to enhance the track-sc syntax, we may be able
6713 * to pass a list of counters to track and allocate them right here using
6714 * stktable_alloc_data_type().
6715 */
6716 }
6717 }
6718
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006719 /* move any "block" rules at the beginning of the http-request rules */
6720 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6721 /* insert block_rules into http_req_rules at the beginning */
6722 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6723 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6724 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6725 curproxy->http_req_rules.n = curproxy->block_rules.n;
6726 LIST_INIT(&curproxy->block_rules);
6727 }
6728
Emeric Brun32da3c42010-09-23 18:39:19 +02006729 if (curproxy->table.peers.name) {
6730 struct peers *curpeers = peers;
6731
6732 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6733 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6734 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006735 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006736 break;
6737 }
6738 }
6739
6740 if (!curpeers) {
6741 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6742 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006743 free((void *)curproxy->table.peers.name);
6744 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006745 cfgerr++;
6746 }
6747 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006748 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6749 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006750 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006751 cfgerr++;
6752 }
6753 }
6754
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006755 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006756 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006757 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6758 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6759 "proxy", curproxy->id);
6760 cfgerr++;
6761 goto out_uri_auth_compat;
6762 }
6763
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006764 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006765 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006766 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006767 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006768
Willy Tarreau95fa4692010-02-01 13:05:50 +01006769 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6770 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006771
6772 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006773 uri_auth_compat_req[i++] = "realm";
6774 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6775 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006776
Willy Tarreau95fa4692010-02-01 13:05:50 +01006777 uri_auth_compat_req[i++] = "unless";
6778 uri_auth_compat_req[i++] = "{";
6779 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6780 uri_auth_compat_req[i++] = "}";
6781 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006782
Willy Tarreauff011f22011-01-06 17:51:27 +01006783 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6784 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006785 cfgerr++;
6786 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006787 }
6788
Willy Tarreauff011f22011-01-06 17:51:27 +01006789 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006790
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006791 if (curproxy->uri_auth->auth_realm) {
6792 free(curproxy->uri_auth->auth_realm);
6793 curproxy->uri_auth->auth_realm = NULL;
6794 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006795
6796 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006797 }
6798out_uri_auth_compat:
6799
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006800 /* compile the log format */
6801 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006802 if (curproxy->conf.logformat_string != default_http_log_format &&
6803 curproxy->conf.logformat_string != default_tcp_log_format &&
6804 curproxy->conf.logformat_string != clf_http_log_format)
6805 free(curproxy->conf.logformat_string);
6806 curproxy->conf.logformat_string = NULL;
6807 free(curproxy->conf.lfs_file);
6808 curproxy->conf.lfs_file = NULL;
6809 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006810 }
6811
Willy Tarreau62a61232013-04-12 18:13:46 +02006812 if (curproxy->conf.logformat_string) {
6813 curproxy->conf.args.ctx = ARGC_LOG;
6814 curproxy->conf.args.file = curproxy->conf.lfs_file;
6815 curproxy->conf.args.line = curproxy->conf.lfs_line;
6816 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006817 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006818 curproxy->conf.args.file = NULL;
6819 curproxy->conf.args.line = 0;
6820 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006821
Willy Tarreau62a61232013-04-12 18:13:46 +02006822 if (curproxy->conf.uniqueid_format_string) {
6823 curproxy->conf.args.ctx = ARGC_UIF;
6824 curproxy->conf.args.file = curproxy->conf.uif_file;
6825 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006826 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08006827 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006828 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006829 curproxy->conf.args.file = NULL;
6830 curproxy->conf.args.line = 0;
6831 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006832
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006833 /* only now we can check if some args remain unresolved.
6834 * This must be done after the users and groups resolution.
6835 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006836 cfgerr += smp_resolve_args(curproxy);
6837 if (!cfgerr)
6838 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006839
Willy Tarreau2738a142006-07-08 17:28:09 +02006840 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006841 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006842 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006843 (!curproxy->timeout.connect ||
6844 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006845 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006846 " | While not properly invalid, you will certainly encounter various problems\n"
6847 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006848 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006849 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006850 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006851 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006852
Willy Tarreau1fa31262007-12-03 00:36:16 +01006853 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6854 * We must still support older configurations, so let's find out whether those
6855 * parameters have been set or must be copied from contimeouts.
6856 */
6857 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006858 if (!curproxy->timeout.tarpit ||
6859 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006860 /* tarpit timeout not set. We search in the following order:
6861 * default.tarpit, curr.connect, default.connect.
6862 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006863 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006864 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006865 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006866 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006867 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006868 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006869 }
6870 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006871 (!curproxy->timeout.queue ||
6872 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006873 /* queue timeout not set. We search in the following order:
6874 * default.queue, curr.connect, default.connect.
6875 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006876 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006877 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006878 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006879 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006880 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006881 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006882 }
6883 }
6884
Willy Tarreau1620ec32011-08-06 17:05:02 +02006885 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006886 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6887 curproxy->check_req = (char *)malloc(curproxy->check_len);
6888 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006889 }
6890
Willy Tarreau215663d2014-06-13 18:30:23 +02006891 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6892 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6893 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6894 proxy_type_str(curproxy), curproxy->id);
6895 err_code |= ERR_WARN;
6896 }
6897
Willy Tarreau193b8c62012-11-22 00:17:38 +01006898 /* ensure that cookie capture length is not too large */
6899 if (curproxy->capture_len >= global.tune.cookie_len) {
6900 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6901 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6902 err_code |= ERR_WARN;
6903 curproxy->capture_len = global.tune.cookie_len - 1;
6904 }
6905
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006906 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006907 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006908 curproxy->req_cap_pool = create_pool("ptrcap",
6909 curproxy->nb_req_cap * sizeof(char *),
6910 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006911 }
6912
6913 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006914 curproxy->rsp_cap_pool = create_pool("ptrcap",
6915 curproxy->nb_rsp_cap * sizeof(char *),
6916 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006917 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006918
Willy Tarreaubaaee002006-06-26 02:48:02 +02006919 /* first, we will invert the servers list order */
6920 newsrv = NULL;
6921 while (curproxy->srv) {
6922 struct server *next;
6923
6924 next = curproxy->srv->next;
6925 curproxy->srv->next = newsrv;
6926 newsrv = curproxy->srv;
6927 if (!next)
6928 break;
6929 curproxy->srv = next;
6930 }
6931
Willy Tarreau17edc812014-01-03 12:14:34 +01006932 /* Check that no server name conflicts. This causes trouble in the stats.
6933 * We only emit a warning for the first conflict affecting each server,
6934 * in order to avoid combinatory explosion if all servers have the same
6935 * name. We do that only for servers which do not have an explicit ID,
6936 * because these IDs were made also for distinguishing them and we don't
6937 * want to annoy people who correctly manage them.
6938 */
6939 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6940 struct server *other_srv;
6941
6942 if (newsrv->puid)
6943 continue;
6944
6945 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6946 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6947 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6948 newsrv->conf.file, newsrv->conf.line,
6949 proxy_type_str(curproxy), curproxy->id,
6950 newsrv->id, other_srv->conf.line);
6951 break;
6952 }
6953 }
6954 }
6955
Willy Tarreaudd701652010-05-25 23:03:02 +02006956 /* assign automatic UIDs to servers which don't have one yet */
6957 next_id = 1;
6958 newsrv = curproxy->srv;
6959 while (newsrv != NULL) {
6960 if (!newsrv->puid) {
6961 /* server ID not set, use automatic numbering with first
6962 * spare entry starting with next_svid.
6963 */
6964 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6965 newsrv->conf.id.key = newsrv->puid = next_id;
6966 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6967 }
6968 next_id++;
6969 newsrv = newsrv->next;
6970 }
6971
Willy Tarreau20697042007-11-15 23:26:18 +01006972 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006973 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006974
Willy Tarreau62c3be22012-01-20 13:12:32 +01006975 /*
6976 * If this server supports a maxconn parameter, it needs a dedicated
6977 * tasks to fill the emptied slots when a connection leaves.
6978 * Also, resolve deferred tracking dependency if needed.
6979 */
6980 newsrv = curproxy->srv;
6981 while (newsrv != NULL) {
6982 if (newsrv->minconn > newsrv->maxconn) {
6983 /* Only 'minconn' was specified, or it was higher than or equal
6984 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6985 * this will avoid further useless expensive computations.
6986 */
6987 newsrv->maxconn = newsrv->minconn;
6988 } else if (newsrv->maxconn && !newsrv->minconn) {
6989 /* minconn was not specified, so we set it to maxconn */
6990 newsrv->minconn = newsrv->maxconn;
6991 }
6992
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006993#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006994 if (newsrv->use_ssl || newsrv->check.use_ssl)
6995 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006996#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006997
Willy Tarreau2f075e92013-12-03 11:11:34 +01006998 /* set the check type on the server */
6999 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7000
Willy Tarreau62c3be22012-01-20 13:12:32 +01007001 if (newsrv->trackit) {
7002 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007003 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007004 char *pname, *sname;
7005
7006 pname = newsrv->trackit;
7007 sname = strrchr(pname, '/');
7008
7009 if (sname)
7010 *sname++ = '\0';
7011 else {
7012 sname = pname;
7013 pname = NULL;
7014 }
7015
7016 if (pname) {
7017 px = findproxy(pname, PR_CAP_BE);
7018 if (!px) {
7019 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7020 proxy_type_str(curproxy), curproxy->id,
7021 newsrv->id, pname);
7022 cfgerr++;
7023 goto next_srv;
7024 }
7025 } else
7026 px = curproxy;
7027
7028 srv = findserver(px, sname);
7029 if (!srv) {
7030 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7031 proxy_type_str(curproxy), curproxy->id,
7032 newsrv->id, sname);
7033 cfgerr++;
7034 goto next_srv;
7035 }
7036
Willy Tarreau32091232014-05-16 13:52:00 +02007037 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7038 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7039 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007040 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007041 "tracking as it does not have any check nor agent enabled.\n",
7042 proxy_type_str(curproxy), curproxy->id,
7043 newsrv->id, px->id, srv->id);
7044 cfgerr++;
7045 goto next_srv;
7046 }
7047
7048 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7049
7050 if (loop) {
7051 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7052 "belongs to a tracking chain looping back to %s/%s.\n",
7053 proxy_type_str(curproxy), curproxy->id,
7054 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007055 cfgerr++;
7056 goto next_srv;
7057 }
7058
7059 if (curproxy != px &&
7060 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7061 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7062 "tracking: disable-on-404 option inconsistency.\n",
7063 proxy_type_str(curproxy), curproxy->id,
7064 newsrv->id, px->id, srv->id);
7065 cfgerr++;
7066 goto next_srv;
7067 }
7068
7069 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007070 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007071 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007072 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007073 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007074 }
7075
7076 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007077 newsrv->tracknext = srv->trackers;
7078 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007079
7080 free(newsrv->trackit);
7081 newsrv->trackit = NULL;
7082 }
7083 next_srv:
7084 newsrv = newsrv->next;
7085 }
7086
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007087 /* We have to initialize the server lookup mechanism depending
7088 * on what LB algorithm was choosen.
7089 */
7090
7091 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7092 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7093 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007094 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7095 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7096 init_server_map(curproxy);
7097 } else {
7098 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7099 fwrr_init_server_groups(curproxy);
7100 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007101 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007102
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007103 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007104 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7105 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7106 fwlc_init_server_tree(curproxy);
7107 } else {
7108 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7109 fas_init_server_tree(curproxy);
7110 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007111 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007112
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007113 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007114 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7115 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7116 chash_init_server_tree(curproxy);
7117 } else {
7118 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7119 init_server_map(curproxy);
7120 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007121 break;
7122 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007123
7124 if (curproxy->options & PR_O_LOGASAP)
7125 curproxy->to_log &= ~LW_BYTES;
7126
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007127 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007128 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007129 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7130 proxy_type_str(curproxy), curproxy->id);
7131 err_code |= ERR_WARN;
7132 }
7133
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007134 if (curproxy->mode != PR_MODE_HTTP) {
7135 int optnum;
7136
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007137 if (curproxy->uri_auth) {
7138 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7139 proxy_type_str(curproxy), curproxy->id);
7140 err_code |= ERR_WARN;
7141 curproxy->uri_auth = NULL;
7142 }
7143
Willy Tarreau87cf5142011-08-19 22:57:24 +02007144 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007145 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7146 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7147 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007148 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007149 }
7150
7151 if (curproxy->options & PR_O_ORGTO) {
7152 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7153 "originalto", proxy_type_str(curproxy), curproxy->id);
7154 err_code |= ERR_WARN;
7155 curproxy->options &= ~PR_O_ORGTO;
7156 }
7157
7158 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7159 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7160 (curproxy->cap & cfg_opts[optnum].cap) &&
7161 (curproxy->options & cfg_opts[optnum].val)) {
7162 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7163 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7164 err_code |= ERR_WARN;
7165 curproxy->options &= ~cfg_opts[optnum].val;
7166 }
7167 }
7168
7169 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7170 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7171 (curproxy->cap & cfg_opts2[optnum].cap) &&
7172 (curproxy->options2 & cfg_opts2[optnum].val)) {
7173 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7174 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7175 err_code |= ERR_WARN;
7176 curproxy->options2 &= ~cfg_opts2[optnum].val;
7177 }
7178 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007179
Pieter Baauwd551fb52013-05-08 22:49:23 +02007180#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007181 if (curproxy->conn_src.bind_hdr_occ) {
7182 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007183 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007184 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007185 err_code |= ERR_WARN;
7186 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007187#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007188 }
7189
Willy Tarreaubaaee002006-06-26 02:48:02 +02007190 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007191 * ensure that we're not cross-dressing a TCP server into HTTP.
7192 */
7193 newsrv = curproxy->srv;
7194 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007195 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007196 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7197 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007198 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007199 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007200
Willy Tarreau0cec3312011-10-31 13:49:26 +01007201 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7202 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7203 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7204 err_code |= ERR_WARN;
7205 }
7206
Willy Tarreauc93cd162014-05-13 15:54:22 +02007207 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007208 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7209 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7210 err_code |= ERR_WARN;
7211 }
7212
Pieter Baauwd551fb52013-05-08 22:49:23 +02007213#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007214 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7215 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007216 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 +01007217 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007218 err_code |= ERR_WARN;
7219 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007220#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007221 newsrv = newsrv->next;
7222 }
7223
Willy Tarreaue42bd962014-09-16 16:21:19 +02007224 /* check if we have a frontend with "tcp-request content" looking at L7
7225 * with no inspect-delay
7226 */
7227 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7228 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7229 if (trule->action == TCP_ACT_CAPTURE &&
7230 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7231 break;
7232 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7233 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7234 break;
7235 }
7236
7237 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7238 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7239 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7240 " This means that these rules will randomly find their contents. This can be fixed by"
7241 " setting the tcp-request inspect-delay.\n",
7242 proxy_type_str(curproxy), curproxy->id);
7243 err_code |= ERR_WARN;
7244 }
7245 }
7246
Willy Tarreauc1a21672009-08-16 22:37:44 +02007247 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007248 if (!curproxy->accept)
7249 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007250
Willy Tarreauc1a21672009-08-16 22:37:44 +02007251 if (curproxy->tcp_req.inspect_delay ||
7252 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007253 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007254
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007255 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007256 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007257 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007258 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007259
7260 /* both TCP and HTTP must check switching rules */
7261 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7262 }
7263
7264 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007265 if (curproxy->tcp_req.inspect_delay ||
7266 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7267 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7268
Emeric Brun97679e72010-09-23 17:56:44 +02007269 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7270 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7271
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007272 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007273 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007274 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007275 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007276
7277 /* If the backend does requires RDP cookie persistence, we have to
7278 * enable the corresponding analyser.
7279 */
7280 if (curproxy->options2 & PR_O2_RDPC_PRST)
7281 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7282 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007283 }
7284
7285 /***********************************************************/
7286 /* At this point, target names have already been resolved. */
7287 /***********************************************************/
7288
7289 /* Check multi-process mode compatibility */
7290
7291 if (global.nbproc > 1 && global.stats_fe) {
7292 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7293 unsigned long mask;
7294
7295 mask = nbits(global.nbproc);
7296 if (global.stats_fe->bind_proc)
7297 mask &= global.stats_fe->bind_proc;
7298
7299 if (bind_conf->bind_proc)
7300 mask &= bind_conf->bind_proc;
7301
7302 /* stop here if more than one process is used */
7303 if (popcount(mask) > 1)
7304 break;
7305 }
7306 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7307 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");
7308 }
7309 }
7310
7311 /* Make each frontend inherit bind-process from its listeners when not specified. */
7312 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7313 if (curproxy->bind_proc)
7314 continue;
7315
7316 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7317 unsigned long mask;
7318
7319 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7320 curproxy->bind_proc |= mask;
7321 }
7322
7323 if (!curproxy->bind_proc)
7324 curproxy->bind_proc = ~0UL;
7325 }
7326
7327 if (global.stats_fe) {
7328 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7329 unsigned long mask;
7330
7331 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7332 global.stats_fe->bind_proc |= mask;
7333 }
7334 if (!global.stats_fe->bind_proc)
7335 global.stats_fe->bind_proc = ~0UL;
7336 }
7337
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007338 /* propagate bindings from frontends to backends. Don't do it if there
7339 * are any fatal errors as we must not call it with unresolved proxies.
7340 */
7341 if (!cfgerr) {
7342 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7343 if (curproxy->cap & PR_CAP_FE)
7344 propagate_processes(curproxy, NULL);
7345 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007346 }
7347
7348 /* Bind each unbound backend to all processes when not specified. */
7349 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7350 if (curproxy->bind_proc)
7351 continue;
7352 curproxy->bind_proc = ~0UL;
7353 }
7354
7355 /*******************************************************/
7356 /* At this step, all proxies have a non-null bind_proc */
7357 /*******************************************************/
7358
7359 /* perform the final checks before creating tasks */
7360
7361 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7362 struct listener *listener;
7363 unsigned int next_id;
7364 int nbproc;
7365
7366 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007367
Emeric Brunc52962f2012-11-15 18:28:02 +01007368#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007369 /* Configure SSL for each bind line.
7370 * Note: if configuration fails at some point, the ->ctx member
7371 * remains NULL so that listeners can later detach.
7372 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007373 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007374 int alloc_ctx;
7375
Emeric Brunc52962f2012-11-15 18:28:02 +01007376 if (!bind_conf->is_ssl) {
7377 if (bind_conf->default_ctx) {
7378 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7379 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7380 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007381 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007382 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007383 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007384 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007385 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007386 cfgerr++;
7387 continue;
7388 }
7389
Emeric Brun8dc60392014-05-09 13:52:00 +02007390 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007391 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007392 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7393 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");
7394 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007395 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007396 cfgerr++;
7397 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007398 }
7399
Emeric Brunfc0421f2012-09-07 17:30:07 +02007400 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007401 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007402 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007403#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007404
Willy Tarreaue6b98942007-10-29 01:09:36 +01007405 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007406 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007407 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007408 if (!listener->luid) {
7409 /* listener ID not set, use automatic numbering with first
7410 * spare entry starting with next_luid.
7411 */
7412 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7413 listener->conf.id.key = listener->luid = next_id;
7414 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007415 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007416 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007417
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007418 /* enable separate counters */
7419 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7420 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007421 if (!listener->name)
7422 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007423 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007424
Willy Tarreaue6b98942007-10-29 01:09:36 +01007425 if (curproxy->options & PR_O_TCP_NOLING)
7426 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007427 if (!listener->maxconn)
7428 listener->maxconn = curproxy->maxconn;
7429 if (!listener->backlog)
7430 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007431 if (!listener->maxaccept)
7432 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7433
7434 /* we want to have an optimal behaviour on single process mode to
7435 * maximize the work at once, but in multi-process we want to keep
7436 * some fairness between processes, so we target half of the max
7437 * number of events to be balanced over all the processes the proxy
7438 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7439 * used to disable the limit.
7440 */
7441 if (listener->maxaccept > 0) {
7442 if (nbproc > 1)
7443 listener->maxaccept = (listener->maxaccept + 1) / 2;
7444 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7445 }
7446
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007447 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007448 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007449 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007450 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007451
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007452 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7453 listener->options |= LI_O_TCP_RULES;
7454
Willy Tarreaude3041d2010-05-31 10:56:17 +02007455 if (curproxy->mon_mask.s_addr)
7456 listener->options |= LI_O_CHK_MONNET;
7457
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007458 /* smart accept mode is automatic in HTTP mode */
7459 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007460 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007461 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7462 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007463 }
7464
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007465 /* Release unused SSL configs */
7466 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7467 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007468 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007469#ifdef USE_OPENSSL
7470 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007471 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007472 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007473 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007474 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007475#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007476 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007477
Willy Tarreau102df612014-05-07 23:56:38 +02007478 if (nbproc > 1) {
7479 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02007480 int count, maxproc = 0;
7481
7482 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7483 count = popcount(bind_conf->bind_proc);
7484 if (count > maxproc)
7485 maxproc = count;
7486 }
7487 /* backends have 0, frontends have 1 or more */
7488 if (maxproc != 1)
7489 Warning("Proxy '%s': in multi-process mode, stats will be"
7490 " limited to process assigned to the current request.\n",
7491 curproxy->id);
7492
Willy Tarreau102df612014-05-07 23:56:38 +02007493 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7494 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7495 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007496 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007497 }
Willy Tarreau102df612014-05-07 23:56:38 +02007498 if (curproxy->appsession_name) {
7499 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7500 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007501 }
Willy Tarreau102df612014-05-07 23:56:38 +02007502 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7503 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7504 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007505 }
7506 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007507
7508 /* create the task associated with the proxy */
7509 curproxy->task = task_new();
7510 if (curproxy->task) {
7511 curproxy->task->context = curproxy;
7512 curproxy->task->process = manage_proxy;
7513 /* no need to queue, it will be done automatically if some
7514 * listener gets limited.
7515 */
7516 curproxy->task->expire = TICK_ETERNITY;
7517 } else {
7518 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7519 curproxy->id);
7520 cfgerr++;
7521 }
Willy Tarreaub369a042014-09-16 13:21:03 +02007522 }
7523
Willy Tarreaufbb78422011-06-05 15:38:35 +02007524 /* automatically compute fullconn if not set. We must not do it in the
7525 * loop above because cross-references are not yet fully resolved.
7526 */
7527 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7528 /* If <fullconn> is not set, let's set it to 10% of the sum of
7529 * the possible incoming frontend's maxconns.
7530 */
7531 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7532 struct proxy *fe;
7533 int total = 0;
7534
7535 /* sum up the number of maxconns of frontends which
7536 * reference this backend at least once or which are
7537 * the same one ('listen').
7538 */
7539 for (fe = proxy; fe; fe = fe->next) {
7540 struct switching_rule *rule;
7541 struct hdr_exp *exp;
7542 int found = 0;
7543
7544 if (!(fe->cap & PR_CAP_FE))
7545 continue;
7546
7547 if (fe == curproxy) /* we're on a "listen" instance */
7548 found = 1;
7549
7550 if (fe->defbe.be == curproxy) /* "default_backend" */
7551 found = 1;
7552
7553 /* check if a "use_backend" rule matches */
7554 if (!found) {
7555 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007556 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007557 found = 1;
7558 break;
7559 }
7560 }
7561 }
7562
7563 /* check if a "reqsetbe" rule matches */
7564 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7565 if (exp->action == ACT_SETBE &&
7566 (struct proxy *)exp->replace == curproxy) {
7567 found = 1;
7568 break;
7569 }
7570 }
7571
7572 /* now we've checked all possible ways to reference a backend
7573 * from a frontend.
7574 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007575 if (!found)
7576 continue;
7577 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007578 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007579 /* we have the sum of the maxconns in <total>. We only
7580 * keep 10% of that sum to set the default fullconn, with
7581 * a hard minimum of 1 (to avoid a divide by zero).
7582 */
7583 curproxy->fullconn = (total + 9) / 10;
7584 if (!curproxy->fullconn)
7585 curproxy->fullconn = 1;
7586 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007587 }
7588
Willy Tarreau056f5682010-06-06 15:51:11 +02007589 /* initialize stick-tables on backend capable proxies. This must not
7590 * be done earlier because the data size may be discovered while parsing
7591 * other proxies.
7592 */
Godbach9703e662013-12-11 21:11:41 +08007593 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007594 if (curproxy->state == PR_STSTOPPED)
7595 continue;
7596
Godbach9703e662013-12-11 21:11:41 +08007597 if (!stktable_init(&curproxy->table)) {
7598 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7599 cfgerr++;
7600 }
7601 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007602
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007603 /*
7604 * Recount currently required checks.
7605 */
7606
7607 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7608 int optnum;
7609
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007610 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7611 if (curproxy->options & cfg_opts[optnum].val)
7612 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007613
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007614 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7615 if (curproxy->options2 & cfg_opts2[optnum].val)
7616 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007617 }
7618
Willy Tarreau122541c2011-09-07 21:24:49 +02007619 if (peers) {
7620 struct peers *curpeers = peers, **last;
7621 struct peer *p, *pb;
7622
7623 /* Remove all peers sections which don't have a valid listener.
7624 * This can happen when a peers section is never referenced and
7625 * does not contain a local peer.
7626 */
7627 last = &peers;
7628 while (*last) {
7629 curpeers = *last;
7630 if (curpeers->peers_fe) {
7631 last = &curpeers->next;
7632 continue;
7633 }
7634
7635 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7636 curpeers->id, localpeer);
7637
7638 p = curpeers->remote;
7639 while (p) {
7640 pb = p->next;
7641 free(p->id);
7642 free(p);
7643 p = pb;
7644 }
7645
7646 /* Destroy and unlink this curpeers section.
7647 * Note: curpeers is backed up into *last.
7648 */
7649 free(curpeers->id);
7650 curpeers = curpeers->next;
7651 free(*last);
7652 *last = curpeers;
7653 }
7654 }
7655
Willy Tarreau34eb6712011-10-24 18:15:04 +02007656 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007657 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007658 MEM_F_SHARED);
7659
Willy Tarreaubb925012009-07-23 13:36:36 +02007660 if (cfgerr > 0)
7661 err_code |= ERR_ALERT | ERR_FATAL;
7662 out:
7663 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007664}
7665
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007666/*
7667 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7668 * parsing sessions.
7669 */
7670void cfg_register_keywords(struct cfg_kw_list *kwl)
7671{
7672 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7673}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007674
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007675/*
7676 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7677 */
7678void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7679{
7680 LIST_DEL(&kwl->list);
7681 LIST_INIT(&kwl->list);
7682}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007683
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007684/* this function register new section in the haproxy configuration file.
7685 * <section_name> is the name of this new section and <section_parser>
7686 * is the called parser. If two section declaration have the same name,
7687 * only the first declared is used.
7688 */
7689int cfg_register_section(char *section_name,
7690 int (*section_parser)(const char *, int, char **, int))
7691{
7692 struct cfg_section *cs;
7693
7694 cs = calloc(1, sizeof(*cs));
7695 if (!cs) {
7696 Alert("register section '%s': out of memory.\n", section_name);
7697 return 0;
7698 }
7699
7700 cs->section_name = section_name;
7701 cs->section_parser = section_parser;
7702
7703 LIST_ADDQ(&sections, &cs->list);
7704
7705 return 1;
7706}
7707
Willy Tarreaubaaee002006-06-26 02:48:02 +02007708/*
7709 * Local variables:
7710 * c-indent-level: 8
7711 * c-basic-offset: 8
7712 * End:
7713 */