blob: ce0517c6a1d2818d1c9ef3fd5e51035a3b6459c7 [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>
Simon Horman0d16a402015-01-30 11:22:58 +090051#include <types/mailers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020052
Willy Tarreaueb0c6142007-05-07 00:53:22 +020053#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010054#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020056#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020058#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020059#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020060#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020061#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020062#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010063#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020064#include <proto/lb_fwlc.h>
65#include <proto/lb_fwrr.h>
66#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020067#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020069#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010070#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020071#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010072#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010073#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020074#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020075#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020076#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020077#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020078#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020079#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020080#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010081#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020082
Emeric Brunfc0421f2012-09-07 17:30:07 +020083#ifdef USE_OPENSSL
84#include <types/ssl_sock.h>
85#include <proto/ssl_sock.h>
86#include <proto/shctx.h>
87#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020088
Willy Tarreauf3c69202006-07-09 16:42:34 +020089/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
90 * ssl-hello-chk option to ensure that the remote server speaks SSL.
91 *
92 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
93 */
94const char sslv3_client_hello_pkt[] = {
95 "\x16" /* ContentType : 0x16 = Hanshake */
96 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
97 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
98 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
99 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
100 "\x03\x00" /* Hello Version : 0x0300 = v3 */
101 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
102 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
103 "\x00" /* Session ID length : empty (no session ID) */
104 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
105 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
106 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
107 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
108 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
109 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
110 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
111 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
112 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
113 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
114 "\x00\x38" "\x00\x39" "\x00\x3A"
115 "\x01" /* Compression Length : 0x01 = 1 byte for types */
116 "\x00" /* Compression Type : 0x00 = NULL compression */
117};
118
Willy Tarreau3842f002009-06-14 11:39:52 +0200119/* various keyword modifiers */
120enum kw_mod {
121 KWM_STD = 0, /* normal */
122 KWM_NO, /* "no" prefixed before the keyword */
123 KWM_DEF, /* "default" prefixed before the keyword */
124};
125
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100126/* permit to store configuration section */
127struct cfg_section {
128 struct list list;
129 char *section_name;
130 int (*section_parser)(const char *, int, char **, int);
131};
132
133/* Used to chain configuration sections definitions. This list
134 * stores struct cfg_section
135 */
136struct list sections = LIST_HEAD_INIT(sections);
137
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100139struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100140 const char *name;
141 unsigned int val;
142 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100143 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100145};
146
147/* proxy->options */
148static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100150 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
151 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
152 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
153 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
154 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
155 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200157 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100158 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100159 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
160 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
161 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
162 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
163 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100164#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100165 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100166#else
167 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100168#endif
169
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100171};
172
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173/* proxy->options2 */
174static const struct cfg_opt cfg_opts2[] =
175{
176#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100177 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
178 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
179 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100180#else
181 { "splice-request", 0, 0, 0, 0 },
182 { "splice-response", 0, 0, 0, 0 },
183 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100185 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
186 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
187 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
188 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
189 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
190 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
191 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
192 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
193 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400194 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100195 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200196 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200197 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100198 { NULL, 0, 0, 0 }
199};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200
Willy Tarreau6daf3432008-01-22 16:44:08 +0100201static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
203int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100204int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200206/* List head of all known configuration keywords */
207static struct cfg_kw_list cfg_keywords = {
208 .list = LIST_HEAD_INIT(cfg_keywords.list)
209};
210
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211/*
212 * converts <str> to a list of listeners which are dynamically allocated.
213 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
214 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
215 * - <port> is a numerical port from 1 to 65535 ;
216 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
217 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200218 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
219 * not NULL, it must be a valid pointer to either NULL or a freeable area that
220 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200222int 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 +0200223{
224 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100225 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 int port, end;
227
228 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200229
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100231 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100232 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233
234 str = next;
235 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100236 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237 *next++ = 0;
238 }
239
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100240 ss2 = str2sa_range(str, &port, &end, err,
241 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
242 if (!ss2)
243 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100245 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100246 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200247 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100248 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200250
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100251 if (!port || !end) {
252 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
253 goto fail;
254 }
255
Emeric Bruned760922010-10-22 17:59:25 +0200256 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200257 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200258 goto fail;
259 }
260
261 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200262 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200263 goto fail;
264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100266 else if (ss2->ss_family == AF_UNSPEC) {
267 socklen_t addr_len;
268
269 /* We want to attach to an already bound fd whose number
270 * is in the addr part of ss2 when cast to sockaddr_in.
271 * Note that by definition there is a single listener.
272 * We still have to determine the address family to
273 * register the correct protocol.
274 */
275 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
276 addr_len = sizeof(*ss2);
277 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
278 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
279 goto fail;
280 }
281
282 port = end = get_host_port(ss2);
283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200284
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100285 /* OK the address looks correct */
286 ss = *ss2;
287
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288 for (; port <= end; port++) {
289 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100290 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200291 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
292 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
293 l->frontend = curproxy;
294 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295
Willy Tarreau40aa0702013-03-10 23:51:38 +0100296 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200298 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100299 l->state = LI_INIT;
300
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100301 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100303 tcpv4_add_listener(l);
304 }
Emeric Bruned760922010-10-22 17:59:25 +0200305 else if (ss.ss_family == AF_INET6) {
306 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
307 tcpv6_add_listener(l);
308 }
309 else {
Emeric Bruned760922010-10-22 17:59:25 +0200310 uxst_add_listener(l);
311 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200312
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200313 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100314 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315 } /* end for(port) */
316 } /* end while(next) */
317 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319 fail:
320 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200321 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200322}
323
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200324/* Report a warning if a rule is placed after a 'tcp-request content' rule.
325 * Return 1 if the warning has been emitted, otherwise 0.
326 */
327int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
328{
329 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
330 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
331 file, line, arg);
332 return 1;
333 }
334 return 0;
335}
336
Willy Tarreau61d18892009-03-31 10:49:21 +0200337/* Report a warning if a rule is placed after a 'block' rule.
338 * Return 1 if the warning has been emitted, otherwise 0.
339 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100340int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200341{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200342 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200343 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
344 file, line, arg);
345 return 1;
346 }
347 return 0;
348}
349
Willy Tarreau5002f572014-04-23 01:32:02 +0200350/* Report a warning if a rule is placed after an 'http_request' rule.
351 * Return 1 if the warning has been emitted, otherwise 0.
352 */
353int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
354{
355 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
356 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
357 file, line, arg);
358 return 1;
359 }
360 return 0;
361}
362
Willy Tarreau61d18892009-03-31 10:49:21 +0200363/* Report a warning if a rule is placed after a reqrewrite rule.
364 * Return 1 if the warning has been emitted, otherwise 0.
365 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100366int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200367{
368 if (proxy->req_exp) {
369 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
370 file, line, arg);
371 return 1;
372 }
373 return 0;
374}
375
376/* Report a warning if a rule is placed after a reqadd rule.
377 * Return 1 if the warning has been emitted, otherwise 0.
378 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100379int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200380{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100381 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200382 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
383 file, line, arg);
384 return 1;
385 }
386 return 0;
387}
388
389/* Report a warning if a rule is placed after a redirect rule.
390 * Return 1 if the warning has been emitted, otherwise 0.
391 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100392int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200393{
394 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
395 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
396 file, line, arg);
397 return 1;
398 }
399 return 0;
400}
401
402/* Report a warning if a rule is placed after a 'use_backend' rule.
403 * Return 1 if the warning has been emitted, otherwise 0.
404 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100405int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200406{
407 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
408 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
409 file, line, arg);
410 return 1;
411 }
412 return 0;
413}
414
Willy Tarreauee445d92014-04-23 01:39:04 +0200415/* Report a warning if a rule is placed after a 'use-server' rule.
416 * Return 1 if the warning has been emitted, otherwise 0.
417 */
418int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
419{
420 if (!LIST_ISEMPTY(&proxy->server_rules)) {
421 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
422 file, line, arg);
423 return 1;
424 }
425 return 0;
426}
427
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200428/* report a warning if a "tcp request connection" rule is dangerously placed */
429int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
430{
431 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
432 warnif_rule_after_block(proxy, file, line, arg) ||
433 warnif_rule_after_http_req(proxy, file, line, arg) ||
434 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
435 warnif_rule_after_reqadd(proxy, file, line, arg) ||
436 warnif_rule_after_redirect(proxy, file, line, arg) ||
437 warnif_rule_after_use_backend(proxy, file, line, arg) ||
438 warnif_rule_after_use_server(proxy, file, line, arg);
439}
440
441/* report a warning if a "tcp request content" rule is dangerously placed */
442int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
443{
444 return warnif_rule_after_block(proxy, file, line, arg) ||
445 warnif_rule_after_http_req(proxy, file, line, arg) ||
446 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
447 warnif_rule_after_reqadd(proxy, file, line, arg) ||
448 warnif_rule_after_redirect(proxy, file, line, arg) ||
449 warnif_rule_after_use_backend(proxy, file, line, arg) ||
450 warnif_rule_after_use_server(proxy, file, line, arg);
451}
452
Willy Tarreau61d18892009-03-31 10:49:21 +0200453/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100454int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200455{
Willy Tarreau5002f572014-04-23 01:32:02 +0200456 return warnif_rule_after_http_req(proxy, file, line, arg) ||
457 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
458 warnif_rule_after_reqadd(proxy, file, line, arg) ||
459 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200460 warnif_rule_after_use_backend(proxy, file, line, arg) ||
461 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200462}
463
464/* report a warning if an http-request rule is dangerously placed */
465int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
466{
Willy Tarreau61d18892009-03-31 10:49:21 +0200467 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
468 warnif_rule_after_reqadd(proxy, file, line, arg) ||
469 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200470 warnif_rule_after_use_backend(proxy, file, line, arg) ||
471 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200472}
473
474/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100475int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200476{
477 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
478 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200479 warnif_rule_after_use_backend(proxy, file, line, arg) ||
480 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200481}
482
483/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100484int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200485{
486 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200487 warnif_rule_after_use_backend(proxy, file, line, arg) ||
488 warnif_rule_after_use_server(proxy, file, line, arg);
489}
490
491/* report a warning if a redirect rule is dangerously placed */
492int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
493{
494 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
495 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200496}
497
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100498/* Report it if a request ACL condition uses some keywords that are incompatible
499 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
500 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
501 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100502 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100503static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100504{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100505 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200506 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100507
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100508 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100509 return 0;
510
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100511 acl = acl_cond_conflicts(cond, where);
512 if (acl) {
513 if (acl->name && *acl->name)
514 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
515 file, line, acl->name, sample_ckp_names(where));
516 else
517 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 +0200518 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100519 return ERR_WARN;
520 }
521 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100522 return 0;
523
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100524 if (acl->name && *acl->name)
525 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200526 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100527 else
528 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200529 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100530 return ERR_WARN;
531}
532
Willy Tarreaubaaee002006-06-26 02:48:02 +0200533/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200534 * parse a line in a <global> section. Returns the error code, 0 if OK, or
535 * any combination of :
536 * - ERR_ABORT: must abort ASAP
537 * - ERR_FATAL: we can continue parsing but not start the service
538 * - ERR_WARN: a warning has been emitted
539 * - ERR_ALERT: an alert has been emitted
540 * Only the two first ones can stop processing, the two others are just
541 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200542 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200543int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200544{
Willy Tarreau058e9072009-07-20 09:30:05 +0200545 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200546 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200547
548 if (!strcmp(args[0], "global")) { /* new section */
549 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200551 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200552 else if (!strcmp(args[0], "ca-base")) {
553#ifdef USE_OPENSSL
554 if (global.ca_base != NULL) {
555 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
556 err_code |= ERR_ALERT;
557 goto out;
558 }
559 if (*(args[1]) == 0) {
560 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT | ERR_FATAL;
562 goto out;
563 }
564 global.ca_base = strdup(args[1]);
565#else
566 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
567 err_code |= ERR_ALERT | ERR_FATAL;
568 goto out;
569#endif
570 }
571 else if (!strcmp(args[0], "crt-base")) {
572#ifdef USE_OPENSSL
573 if (global.crt_base != NULL) {
574 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
575 err_code |= ERR_ALERT;
576 goto out;
577 }
578 if (*(args[1]) == 0) {
579 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
580 err_code |= ERR_ALERT | ERR_FATAL;
581 goto out;
582 }
583 global.crt_base = strdup(args[1]);
584#else
585 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
586 err_code |= ERR_ALERT | ERR_FATAL;
587 goto out;
588#endif
589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 else if (!strcmp(args[0], "daemon")) {
591 global.mode |= MODE_DAEMON;
592 }
593 else if (!strcmp(args[0], "debug")) {
594 global.mode |= MODE_DEBUG;
595 }
596 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100597 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200598 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200599 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100600 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200601 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100603 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200604 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100605 else if (!strcmp(args[0], "nosplice")) {
606 global.tune.options &= ~GTUNE_USE_SPLICE;
607 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200608 else if (!strcmp(args[0], "nogetaddrinfo")) {
609 global.tune.options &= ~GTUNE_USE_GAI;
610 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611 else if (!strcmp(args[0], "quiet")) {
612 global.mode |= MODE_QUIET;
613 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200614 else if (!strcmp(args[0], "tune.maxpollevents")) {
615 if (global.tune.maxpollevents != 0) {
616 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200617 err_code |= ERR_ALERT;
618 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200619 }
620 if (*(args[1]) == 0) {
621 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200622 err_code |= ERR_ALERT | ERR_FATAL;
623 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200624 }
625 global.tune.maxpollevents = atol(args[1]);
626 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100627 else if (!strcmp(args[0], "tune.maxaccept")) {
628 if (global.tune.maxaccept != 0) {
629 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200630 err_code |= ERR_ALERT;
631 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100632 }
633 if (*(args[1]) == 0) {
634 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200635 err_code |= ERR_ALERT | ERR_FATAL;
636 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100637 }
638 global.tune.maxaccept = atol(args[1]);
639 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200640 else if (!strcmp(args[0], "tune.chksize")) {
641 if (*(args[1]) == 0) {
642 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
643 err_code |= ERR_ALERT | ERR_FATAL;
644 goto out;
645 }
646 global.tune.chksize = atol(args[1]);
647 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200648#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200649 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
650 global.tune.sslprivatecache = 1;
651 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100652 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200653 if (*(args[1]) == 0) {
654 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
655 err_code |= ERR_ALERT | ERR_FATAL;
656 goto out;
657 }
658 global.tune.sslcachesize = atol(args[1]);
659 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100660 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
661 unsigned int ssllifetime;
662 const char *res;
663
664 if (*(args[1]) == 0) {
665 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
666 err_code |= ERR_ALERT | ERR_FATAL;
667 goto out;
668 }
669
670 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
671 if (res) {
672 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
673 file, linenum, *res, args[0]);
674 err_code |= ERR_ALERT | ERR_FATAL;
675 goto out;
676 }
677
678 global.tune.ssllifetime = ssllifetime;
679 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100680 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
681 if (*(args[1]) == 0) {
682 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
683 err_code |= ERR_ALERT | ERR_FATAL;
684 goto out;
685 }
686 global.tune.ssl_max_record = atol(args[1]);
687 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200688 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
689 if (*(args[1]) == 0) {
690 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
691 err_code |= ERR_ALERT | ERR_FATAL;
692 goto out;
693 }
694 global.tune.ssl_default_dh_param = atol(args[1]);
695 if (global.tune.ssl_default_dh_param < 1024) {
696 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
697 err_code |= ERR_ALERT | ERR_FATAL;
698 goto out;
699 }
700 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200701#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100702 else if (!strcmp(args[0], "tune.buffers.limit")) {
703 if (*(args[1]) == 0) {
704 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708 global.tune.buf_limit = atol(args[1]);
709 if (global.tune.buf_limit) {
710 if (global.tune.buf_limit < 3)
711 global.tune.buf_limit = 3;
712 if (global.tune.buf_limit <= global.tune.reserved_bufs)
713 global.tune.buf_limit = global.tune.reserved_bufs + 1;
714 }
715 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100716 else if (!strcmp(args[0], "tune.buffers.reserve")) {
717 if (*(args[1]) == 0) {
718 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
721 }
722 global.tune.reserved_bufs = atol(args[1]);
723 if (global.tune.reserved_bufs < 2)
724 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100725 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
726 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100727 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200728 else if (!strcmp(args[0], "tune.bufsize")) {
729 if (*(args[1]) == 0) {
730 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
731 err_code |= ERR_ALERT | ERR_FATAL;
732 goto out;
733 }
734 global.tune.bufsize = atol(args[1]);
735 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
736 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100737 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100738 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200739 }
740 else if (!strcmp(args[0], "tune.maxrewrite")) {
741 if (*(args[1]) == 0) {
742 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
743 err_code |= ERR_ALERT | ERR_FATAL;
744 goto out;
745 }
746 global.tune.maxrewrite = atol(args[1]);
747 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
748 global.tune.maxrewrite = global.tune.bufsize / 2;
749 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100750 else if (!strcmp(args[0], "tune.idletimer")) {
751 unsigned int idle;
752 const char *res;
753
754 if (*(args[1]) == 0) {
755 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
756 err_code |= ERR_ALERT | ERR_FATAL;
757 goto out;
758 }
759
760 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
761 if (res) {
762 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
763 file, linenum, *res, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
767
768 if (idle > 65535) {
769 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
772 }
773 global.tune.idle_timer = idle;
774 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100775 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
776 if (global.tune.client_rcvbuf != 0) {
777 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
778 err_code |= ERR_ALERT;
779 goto out;
780 }
781 if (*(args[1]) == 0) {
782 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
783 err_code |= ERR_ALERT | ERR_FATAL;
784 goto out;
785 }
786 global.tune.client_rcvbuf = atol(args[1]);
787 }
788 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
789 if (global.tune.server_rcvbuf != 0) {
790 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
791 err_code |= ERR_ALERT;
792 goto out;
793 }
794 if (*(args[1]) == 0) {
795 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
798 }
799 global.tune.server_rcvbuf = atol(args[1]);
800 }
801 else if (!strcmp(args[0], "tune.sndbuf.client")) {
802 if (global.tune.client_sndbuf != 0) {
803 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
804 err_code |= ERR_ALERT;
805 goto out;
806 }
807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
811 }
812 global.tune.client_sndbuf = atol(args[1]);
813 }
814 else if (!strcmp(args[0], "tune.sndbuf.server")) {
815 if (global.tune.server_sndbuf != 0) {
816 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
817 err_code |= ERR_ALERT;
818 goto out;
819 }
820 if (*(args[1]) == 0) {
821 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
822 err_code |= ERR_ALERT | ERR_FATAL;
823 goto out;
824 }
825 global.tune.server_sndbuf = atol(args[1]);
826 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200827 else if (!strcmp(args[0], "tune.pipesize")) {
828 if (*(args[1]) == 0) {
829 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
832 }
833 global.tune.pipesize = atol(args[1]);
834 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100835 else if (!strcmp(args[0], "tune.http.cookielen")) {
836 if (*(args[1]) == 0) {
837 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
838 err_code |= ERR_ALERT | ERR_FATAL;
839 goto out;
840 }
841 global.tune.cookie_len = atol(args[1]) + 1;
842 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200843 else if (!strcmp(args[0], "tune.http.maxhdr")) {
844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849 global.tune.max_http_hdr = atol(args[1]);
850 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100851 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
852#ifdef USE_ZLIB
853 if (*args[1]) {
854 global.tune.zlibmemlevel = atoi(args[1]);
855 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
856 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
857 file, linenum, args[0]);
858 err_code |= ERR_ALERT | ERR_FATAL;
859 goto out;
860 }
861 } else {
862 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
863 file, linenum, args[0]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867#else
868 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
869 err_code |= ERR_ALERT | ERR_FATAL;
870 goto out;
871#endif
872 }
873 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
874#ifdef USE_ZLIB
875 if (*args[1]) {
876 global.tune.zlibwindowsize = atoi(args[1]);
877 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
878 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
879 file, linenum, args[0]);
880 err_code |= ERR_ALERT | ERR_FATAL;
881 goto out;
882 }
883 } else {
884 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
885 file, linenum, args[0]);
886 err_code |= ERR_ALERT | ERR_FATAL;
887 goto out;
888 }
889#else
890 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
891 err_code |= ERR_ALERT | ERR_FATAL;
892 goto out;
893#endif
894 }
William Lallemandf3747832012-11-09 12:33:10 +0100895 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
896 if (*args[1]) {
897 global.tune.comp_maxlevel = atoi(args[1]);
898 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
899 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
900 file, linenum, args[0]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904 } else {
905 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
906 file, linenum, args[0]);
907 err_code |= ERR_ALERT | ERR_FATAL;
908 goto out;
909 }
910 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200911 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
912 if (*args[1]) {
913 global.tune.pattern_cache = atoi(args[1]);
914 if (global.tune.pattern_cache < 0) {
915 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
916 file, linenum, args[0]);
917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
919 }
920 } else {
921 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
922 file, linenum, args[0]);
923 err_code |= ERR_ALERT | ERR_FATAL;
924 goto out;
925 }
926 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 else if (!strcmp(args[0], "uid")) {
928 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200929 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200930 err_code |= ERR_ALERT;
931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 }
933 if (*(args[1]) == 0) {
934 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT | ERR_FATAL;
936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
938 global.uid = atol(args[1]);
939 }
940 else if (!strcmp(args[0], "gid")) {
941 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200942 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200943 err_code |= ERR_ALERT;
944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200945 }
946 if (*(args[1]) == 0) {
947 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200948 err_code |= ERR_ALERT | ERR_FATAL;
949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950 }
951 global.gid = atol(args[1]);
952 }
Simon Horman98637e52014-06-20 12:30:16 +0900953 else if (!strcmp(args[0], "external-check")) {
954 global.external_check = 1;
955 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200956 /* user/group name handling */
957 else if (!strcmp(args[0], "user")) {
958 struct passwd *ha_user;
959 if (global.uid != 0) {
960 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200961 err_code |= ERR_ALERT;
962 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200963 }
964 errno = 0;
965 ha_user = getpwnam(args[1]);
966 if (ha_user != NULL) {
967 global.uid = (int)ha_user->pw_uid;
968 }
969 else {
970 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 +0200971 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200972 }
973 }
974 else if (!strcmp(args[0], "group")) {
975 struct group *ha_group;
976 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200977 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200978 err_code |= ERR_ALERT;
979 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200980 }
981 errno = 0;
982 ha_group = getgrnam(args[1]);
983 if (ha_group != NULL) {
984 global.gid = (int)ha_group->gr_gid;
985 }
986 else {
987 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 +0200988 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200989 }
990 }
991 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200993 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.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100999 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1000 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1001 file, linenum, args[0], LONGBITS, global.nbproc);
1002 err_code |= ERR_ALERT | ERR_FATAL;
1003 goto out;
1004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001005 }
1006 else if (!strcmp(args[0], "maxconn")) {
1007 if (global.maxconn != 0) {
1008 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001009 err_code |= ERR_ALERT;
1010 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001011 }
1012 if (*(args[1]) == 0) {
1013 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001014 err_code |= ERR_ALERT | ERR_FATAL;
1015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001016 }
1017 global.maxconn = atol(args[1]);
1018#ifdef SYSTEM_MAXCONN
1019 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1020 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);
1021 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001022 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001023 }
1024#endif /* SYSTEM_MAXCONN */
1025 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001026 else if (!strcmp(args[0], "maxsslconn")) {
1027#ifdef USE_OPENSSL
1028 if (*(args[1]) == 0) {
1029 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1030 err_code |= ERR_ALERT | ERR_FATAL;
1031 goto out;
1032 }
1033 global.maxsslconn = atol(args[1]);
1034#else
Emeric Brun0914df82012-10-02 18:45:42 +02001035 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1036 err_code |= ERR_ALERT | ERR_FATAL;
1037 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001038#endif
1039 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001040 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1041#ifdef USE_OPENSSL
1042 if (*(args[1]) == 0) {
1043 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1044 err_code |= ERR_ALERT | ERR_FATAL;
1045 goto out;
1046 }
1047 free(global.listen_default_ciphers);
1048 global.listen_default_ciphers = strdup(args[1]);
1049#else
1050 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1051 err_code |= ERR_ALERT | ERR_FATAL;
1052 goto out;
1053#endif
1054 }
1055 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1056#ifdef USE_OPENSSL
1057 if (*(args[1]) == 0) {
1058 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1059 err_code |= ERR_ALERT | ERR_FATAL;
1060 goto out;
1061 }
1062 free(global.connect_default_ciphers);
1063 global.connect_default_ciphers = strdup(args[1]);
1064#else
1065 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1066 err_code |= ERR_ALERT | ERR_FATAL;
1067 goto out;
1068#endif
1069 }
Emeric Brun850efd52014-01-29 12:24:34 +01001070 else if (!strcmp(args[0], "ssl-server-verify")) {
1071 if (*(args[1]) == 0) {
1072 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1073 err_code |= ERR_ALERT | ERR_FATAL;
1074 goto out;
1075 }
1076 if (strcmp(args[1],"none") == 0)
1077 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1078 else if (strcmp(args[1],"required") == 0)
1079 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1080 else {
1081 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1082 err_code |= ERR_ALERT | ERR_FATAL;
1083 goto out;
1084 }
1085 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001086 else if (!strcmp(args[0], "maxconnrate")) {
1087 if (global.cps_lim != 0) {
1088 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1089 err_code |= ERR_ALERT;
1090 goto out;
1091 }
1092 if (*(args[1]) == 0) {
1093 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1094 err_code |= ERR_ALERT | ERR_FATAL;
1095 goto out;
1096 }
1097 global.cps_lim = atol(args[1]);
1098 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001099 else if (!strcmp(args[0], "maxsessrate")) {
1100 if (global.sps_lim != 0) {
1101 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1102 err_code |= ERR_ALERT;
1103 goto out;
1104 }
1105 if (*(args[1]) == 0) {
1106 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1107 err_code |= ERR_ALERT | ERR_FATAL;
1108 goto out;
1109 }
1110 global.sps_lim = atol(args[1]);
1111 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001112 else if (!strcmp(args[0], "maxsslrate")) {
1113 if (global.ssl_lim != 0) {
1114 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1115 err_code |= ERR_ALERT;
1116 goto out;
1117 }
1118 if (*(args[1]) == 0) {
1119 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1120 err_code |= ERR_ALERT | ERR_FATAL;
1121 goto out;
1122 }
1123 global.ssl_lim = atol(args[1]);
1124 }
William Lallemandd85f9172012-11-09 17:05:39 +01001125 else if (!strcmp(args[0], "maxcomprate")) {
1126 if (*(args[1]) == 0) {
1127 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1128 err_code |= ERR_ALERT | ERR_FATAL;
1129 goto out;
1130 }
1131 global.comp_rate_lim = atoi(args[1]) * 1024;
1132 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001133 else if (!strcmp(args[0], "maxpipes")) {
1134 if (global.maxpipes != 0) {
1135 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT;
1137 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001138 }
1139 if (*(args[1]) == 0) {
1140 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001141 err_code |= ERR_ALERT | ERR_FATAL;
1142 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001143 }
1144 global.maxpipes = atol(args[1]);
1145 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001146 else if (!strcmp(args[0], "maxzlibmem")) {
1147 if (*(args[1]) == 0) {
1148 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1149 err_code |= ERR_ALERT | ERR_FATAL;
1150 goto out;
1151 }
William Lallemande3a7d992012-11-20 11:25:20 +01001152 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001153 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001154 else if (!strcmp(args[0], "maxcompcpuusage")) {
1155 if (*(args[1]) == 0) {
1156 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1157 err_code |= ERR_ALERT | ERR_FATAL;
1158 goto out;
1159 }
1160 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001161 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001162 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1163 err_code |= ERR_ALERT | ERR_FATAL;
1164 goto out;
1165 }
1166}
1167
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 else if (!strcmp(args[0], "ulimit-n")) {
1169 if (global.rlimit_nofile != 0) {
1170 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001171 err_code |= ERR_ALERT;
1172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173 }
1174 if (*(args[1]) == 0) {
1175 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001176 err_code |= ERR_ALERT | ERR_FATAL;
1177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001178 }
1179 global.rlimit_nofile = atol(args[1]);
1180 }
1181 else if (!strcmp(args[0], "chroot")) {
1182 if (global.chroot != NULL) {
1183 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001184 err_code |= ERR_ALERT;
1185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001186 }
1187 if (*(args[1]) == 0) {
1188 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001189 err_code |= ERR_ALERT | ERR_FATAL;
1190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001191 }
1192 global.chroot = strdup(args[1]);
1193 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001194 else if (!strcmp(args[0], "description")) {
1195 int i, len=0;
1196 char *d;
1197
1198 if (!*args[1]) {
1199 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1200 file, linenum, args[0]);
1201 err_code |= ERR_ALERT | ERR_FATAL;
1202 goto out;
1203 }
1204
Willy Tarreau348acfe2014-04-14 15:00:39 +02001205 for (i = 1; *args[i]; i++)
1206 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001207
1208 if (global.desc)
1209 free(global.desc);
1210
1211 global.desc = d = (char *)calloc(1, len);
1212
Willy Tarreau348acfe2014-04-14 15:00:39 +02001213 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1214 for (i = 2; *args[i]; i++)
1215 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001216 }
1217 else if (!strcmp(args[0], "node")) {
1218 int i;
1219 char c;
1220
1221 for (i=0; args[1][i]; i++) {
1222 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001223 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1224 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001225 break;
1226 }
1227
1228 if (!i || args[1][i]) {
1229 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1230 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1231 file, linenum, args[0]);
1232 err_code |= ERR_ALERT | ERR_FATAL;
1233 goto out;
1234 }
1235
1236 if (global.node)
1237 free(global.node);
1238
1239 global.node = strdup(args[1]);
1240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001241 else if (!strcmp(args[0], "pidfile")) {
1242 if (global.pidfile != NULL) {
1243 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001244 err_code |= ERR_ALERT;
1245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001246 }
1247 if (*(args[1]) == 0) {
1248 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001251 }
1252 global.pidfile = strdup(args[1]);
1253 }
Emeric Bruned760922010-10-22 17:59:25 +02001254 else if (!strcmp(args[0], "unix-bind")) {
1255 int cur_arg = 1;
1256 while (*(args[cur_arg])) {
1257 if (!strcmp(args[cur_arg], "prefix")) {
1258 if (global.unix_bind.prefix != NULL) {
1259 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1260 err_code |= ERR_ALERT;
1261 cur_arg += 2;
1262 continue;
1263 }
1264
1265 if (*(args[cur_arg+1]) == 0) {
1266 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1267 err_code |= ERR_ALERT | ERR_FATAL;
1268 goto out;
1269 }
1270 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1271 cur_arg += 2;
1272 continue;
1273 }
1274
1275 if (!strcmp(args[cur_arg], "mode")) {
1276
1277 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1278 cur_arg += 2;
1279 continue;
1280 }
1281
1282 if (!strcmp(args[cur_arg], "uid")) {
1283
1284 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1285 cur_arg += 2;
1286 continue;
1287 }
1288
1289 if (!strcmp(args[cur_arg], "gid")) {
1290
1291 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1292 cur_arg += 2;
1293 continue;
1294 }
1295
1296 if (!strcmp(args[cur_arg], "user")) {
1297 struct passwd *user;
1298
1299 user = getpwnam(args[cur_arg + 1]);
1300 if (!user) {
1301 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1302 file, linenum, args[0], args[cur_arg + 1 ]);
1303 err_code |= ERR_ALERT | ERR_FATAL;
1304 goto out;
1305 }
1306
1307 global.unix_bind.ux.uid = user->pw_uid;
1308 cur_arg += 2;
1309 continue;
1310 }
1311
1312 if (!strcmp(args[cur_arg], "group")) {
1313 struct group *group;
1314
1315 group = getgrnam(args[cur_arg + 1]);
1316 if (!group) {
1317 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1318 file, linenum, args[0], args[cur_arg + 1 ]);
1319 err_code |= ERR_ALERT | ERR_FATAL;
1320 goto out;
1321 }
1322
1323 global.unix_bind.ux.gid = group->gr_gid;
1324 cur_arg += 2;
1325 continue;
1326 }
1327
Willy Tarreaub48f9582011-09-05 01:17:06 +02001328 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001329 file, linenum, args[0]);
1330 err_code |= ERR_ALERT | ERR_FATAL;
1331 goto out;
1332 }
1333 }
William Lallemand0f99e342011-10-12 17:50:54 +02001334 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1335 /* delete previous herited or defined syslog servers */
1336 struct logsrv *back;
1337 struct logsrv *tmp;
1338
1339 if (*(args[1]) != 0) {
1340 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
1343 }
1344
1345 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1346 LIST_DEL(&tmp->list);
1347 free(tmp);
1348 }
1349 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001350 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001351 struct sockaddr_storage *sk;
1352 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001353 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001354 int arg = 0;
1355 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001356
Willy Tarreaubaaee002006-06-26 02:48:02 +02001357 if (*(args[1]) == 0 || *(args[2]) == 0) {
1358 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001359 err_code |= ERR_ALERT | ERR_FATAL;
1360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001361 }
William Lallemand0f99e342011-10-12 17:50:54 +02001362
1363 logsrv = calloc(1, sizeof(struct logsrv));
1364
Willy Tarreau18324f52014-06-27 18:10:07 +02001365 /* just after the address, a length may be specified */
1366 if (strcmp(args[arg+2], "len") == 0) {
1367 len = atoi(args[arg+3]);
1368 if (len < 80 || len > 65535) {
1369 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1370 file, linenum, args[arg+3]);
1371 err_code |= ERR_ALERT | ERR_FATAL;
1372 goto out;
1373 }
1374 logsrv->maxlen = len;
1375
1376 /* skip these two args */
1377 arg += 2;
1378 }
1379 else
1380 logsrv->maxlen = MAX_SYSLOG_LEN;
1381
1382 if (logsrv->maxlen > global.max_syslog_len) {
1383 global.max_syslog_len = logsrv->maxlen;
1384 logline = realloc(logline, global.max_syslog_len + 1);
1385 }
1386
1387 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001388 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001389 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001390 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001391 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392 }
1393
William Lallemand0f99e342011-10-12 17:50:54 +02001394 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001395 if (*(args[arg+3])) {
1396 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001397 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001398 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001399 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001400 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401 }
1402 }
1403
William Lallemand0f99e342011-10-12 17:50:54 +02001404 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001405 if (*(args[arg+4])) {
1406 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001407 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001408 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001409 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001410 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001411 }
1412 }
1413
Willy Tarreau902636f2013-03-10 19:44:48 +01001414 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001415 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001416 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001417 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001418 free(logsrv);
1419 goto out;
1420 }
1421 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001422
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001423 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001424 if (port1 != port2) {
1425 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1426 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001427 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001428 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001429 goto out;
1430 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001431
William Lallemand0f99e342011-10-12 17:50:54 +02001432 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001433 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001434 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001435 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001436
William Lallemand0f99e342011-10-12 17:50:54 +02001437 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001438 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001439 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1440 char *name;
1441 int len;
1442
1443 if (global.log_send_hostname != NULL) {
1444 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1445 err_code |= ERR_ALERT;
1446 goto out;
1447 }
1448
1449 if (*(args[1]))
1450 name = args[1];
1451 else
1452 name = hostname;
1453
1454 len = strlen(name);
1455
1456 /* We'll add a space after the name to respect the log format */
1457 free(global.log_send_hostname);
1458 global.log_send_hostname = malloc(len + 2);
1459 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1460 }
Kevinm48936af2010-12-22 16:08:21 +00001461 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1462 if (*(args[1]) == 0) {
1463 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1464 err_code |= ERR_ALERT | ERR_FATAL;
1465 goto out;
1466 }
1467 free(global.log_tag);
1468 global.log_tag = strdup(args[1]);
1469 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001470 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1471 if (global.spread_checks != 0) {
1472 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001473 err_code |= ERR_ALERT;
1474 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001475 }
1476 if (*(args[1]) == 0) {
1477 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001478 err_code |= ERR_ALERT | ERR_FATAL;
1479 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001480 }
1481 global.spread_checks = atol(args[1]);
1482 if (global.spread_checks < 0 || global.spread_checks > 50) {
1483 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001484 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001485 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001486 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001487 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1488 const char *err;
1489 unsigned int val;
1490
1491
1492 if (*(args[1]) == 0) {
1493 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1494 err_code |= ERR_ALERT | ERR_FATAL;
1495 goto out;
1496 }
1497
1498 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1499 if (err) {
1500 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1501 err_code |= ERR_ALERT | ERR_FATAL;
1502 }
1503 global.max_spread_checks = val;
1504 if (global.max_spread_checks < 0) {
1505 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1506 err_code |= ERR_ALERT | ERR_FATAL;
1507 }
1508 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001509 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1510#ifdef USE_CPU_AFFINITY
1511 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001512 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001513 unsigned long cpus = 0;
1514
1515 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001516 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001517 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001518 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001519 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001520 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001521 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001522 proc = atol(args[1]);
1523 if (proc >= 1 && proc <= LONGBITS)
1524 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001525 }
1526
1527 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001528 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",
1529 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
1532 }
1533
1534 cur_arg = 2;
1535 while (*args[cur_arg]) {
1536 unsigned int low, high;
1537
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001538 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001539 char *dash = strchr(args[cur_arg], '-');
1540
1541 low = high = str2uic(args[cur_arg]);
1542 if (dash)
1543 high = str2uic(dash + 1);
1544
1545 if (high < low) {
1546 unsigned int swap = low;
1547 low = high;
1548 high = swap;
1549 }
1550
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001551 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001552 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001553 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001554 err_code |= ERR_ALERT | ERR_FATAL;
1555 goto out;
1556 }
1557
1558 while (low <= high)
1559 cpus |= 1UL << low++;
1560 }
1561 else {
1562 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1563 file, linenum, args[0], args[cur_arg]);
1564 err_code |= ERR_ALERT | ERR_FATAL;
1565 goto out;
1566 }
1567 cur_arg++;
1568 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001569 for (i = 0; i < LONGBITS; i++)
1570 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001571 global.cpu_map[i] = cpus;
1572#else
1573 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1574 err_code |= ERR_ALERT | ERR_FATAL;
1575 goto out;
1576#endif
1577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001579 struct cfg_kw_list *kwl;
1580 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001581 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001582
1583 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1584 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1585 if (kwl->kw[index].section != CFG_GLOBAL)
1586 continue;
1587 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001588 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001589 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001590 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001591 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001592 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001593 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001594 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001595 err_code |= ERR_WARN;
1596 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001597 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001598 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001599 }
1600 }
1601 }
1602
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001604 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001606
Willy Tarreau058e9072009-07-20 09:30:05 +02001607 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001608 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001609 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001610}
1611
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001612void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001613{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001614 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615 defproxy.mode = PR_MODE_TCP;
1616 defproxy.state = PR_STNEW;
1617 defproxy.maxconn = cfg_maxpconn;
1618 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001619
Simon Horman66183002013-02-23 10:16:43 +09001620 defproxy.defsrv.check.inter = DEF_CHKINTR;
1621 defproxy.defsrv.check.fastinter = 0;
1622 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001623 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1624 defproxy.defsrv.agent.fastinter = 0;
1625 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001626 defproxy.defsrv.check.rise = DEF_RISETIME;
1627 defproxy.defsrv.check.fall = DEF_FALLTIME;
1628 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1629 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001630 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001631 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001632 defproxy.defsrv.maxqueue = 0;
1633 defproxy.defsrv.minconn = 0;
1634 defproxy.defsrv.maxconn = 0;
1635 defproxy.defsrv.slowstart = 0;
1636 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1637 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1638 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001639
1640 defproxy.email_alert.level = LOG_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001641}
1642
Willy Tarreauade5ec42010-01-28 19:33:49 +01001643
Willy Tarreau63af98d2014-05-18 08:11:41 +02001644/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1645 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1646 * ERR_FATAL in case of error.
1647 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001648static int create_cond_regex_rule(const char *file, int line,
1649 struct proxy *px, int dir, int action, int flags,
1650 const char *cmd, const char *reg, const char *repl,
1651 const char **cond_start)
1652{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001653 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001654 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001655 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001656 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001657 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001658 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001659 int cs;
1660 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001661
1662 if (px == &defproxy) {
1663 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001664 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001665 goto err;
1666 }
1667
1668 if (*reg == 0) {
1669 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001670 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001671 goto err;
1672 }
1673
1674 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001675 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001676
Willy Tarreau5321c422010-01-28 20:35:13 +01001677 if (cond_start &&
1678 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001679 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1680 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1681 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001682 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001683 goto err;
1684 }
1685 }
1686 else if (cond_start && **cond_start) {
1687 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1688 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001689 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001690 goto err;
1691 }
1692
Willy Tarreau63af98d2014-05-18 08:11:41 +02001693 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001694 (dir == SMP_OPT_DIR_REQ) ?
1695 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1696 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1697 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001698
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001699 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001700 if (!preg) {
1701 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001702 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001703 goto err;
1704 }
1705
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001706 cs = !(flags & REG_ICASE);
1707 cap = !(flags & REG_NOSUB);
1708 error = NULL;
1709 if (!regex_comp(reg, preg, cs, cap, &error)) {
1710 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1711 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001712 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001713 goto err;
1714 }
1715
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001716 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001717 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001718 if (repl && err) {
1719 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1720 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001721 ret_code |= ERR_ALERT | ERR_FATAL;
1722 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001723 }
1724
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001725 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001726 ret_code |= ERR_WARN;
1727
1728 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001729
Willy Tarreau63af98d2014-05-18 08:11:41 +02001730 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001731 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001732 err:
1733 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001734 free(errmsg);
1735 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001736}
1737
Willy Tarreaubaaee002006-06-26 02:48:02 +02001738/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001739 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001740 * Returns the error code, 0 if OK, or any combination of :
1741 * - ERR_ABORT: must abort ASAP
1742 * - ERR_FATAL: we can continue parsing but not start the service
1743 * - ERR_WARN: a warning has been emitted
1744 * - ERR_ALERT: an alert has been emitted
1745 * Only the two first ones can stop processing, the two others are just
1746 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001747 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001748int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1749{
1750 static struct peers *curpeers = NULL;
1751 struct peer *newpeer = NULL;
1752 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001753 struct bind_conf *bind_conf;
1754 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001755 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001756 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001757
1758 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001759 if (!*args[1]) {
1760 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001761 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001762 goto out;
1763 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001764
1765 err = invalid_char(args[1]);
1766 if (err) {
1767 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1768 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001769 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001770 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001771 }
1772
1773 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1774 /*
1775 * If there are two proxies with the same name only following
1776 * combinations are allowed:
1777 */
1778 if (strcmp(curpeers->id, args[1]) == 0) {
1779 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1780 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1781 err_code |= ERR_WARN;
1782 }
1783 }
1784
1785 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1786 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1787 err_code |= ERR_ALERT | ERR_ABORT;
1788 goto out;
1789 }
1790
1791 curpeers->next = peers;
1792 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001793 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001794 curpeers->conf.line = linenum;
1795 curpeers->last_change = now.tv_sec;
1796 curpeers->id = strdup(args[1]);
1797 }
1798 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001799 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001800 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001801 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001802
1803 if (!*args[2]) {
1804 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1805 file, linenum, args[0]);
1806 err_code |= ERR_ALERT | ERR_FATAL;
1807 goto out;
1808 }
1809
1810 err = invalid_char(args[1]);
1811 if (err) {
1812 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1813 file, linenum, *err, args[1]);
1814 err_code |= ERR_ALERT | ERR_FATAL;
1815 goto out;
1816 }
1817
1818 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1819 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1820 err_code |= ERR_ALERT | ERR_ABORT;
1821 goto out;
1822 }
1823
1824 /* the peers are linked backwards first */
1825 curpeers->count++;
1826 newpeer->next = curpeers->remote;
1827 curpeers->remote = newpeer;
1828 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001829 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001830 newpeer->conf.line = linenum;
1831
1832 newpeer->last_change = now.tv_sec;
1833 newpeer->id = strdup(args[1]);
1834
Willy Tarreau902636f2013-03-10 19:44:48 +01001835 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001836 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001837 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001838 err_code |= ERR_ALERT | ERR_FATAL;
1839 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001840 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001841
1842 proto = protocol_by_family(sk->ss_family);
1843 if (!proto || !proto->connect) {
1844 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1845 file, linenum, args[0], args[1]);
1846 err_code |= ERR_ALERT | ERR_FATAL;
1847 goto out;
1848 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001849
1850 if (port1 != port2) {
1851 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1852 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001853 err_code |= ERR_ALERT | ERR_FATAL;
1854 goto out;
1855 }
1856
Willy Tarreau2aa38802013-02-20 19:20:59 +01001857 if (!port1) {
1858 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1859 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001860 err_code |= ERR_ALERT | ERR_FATAL;
1861 goto out;
1862 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001863
Emeric Brun32da3c42010-09-23 18:39:19 +02001864 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001865 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001866 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001867 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001868
Emeric Brun32da3c42010-09-23 18:39:19 +02001869 if (strcmp(newpeer->id, localpeer) == 0) {
1870 /* Current is local peer, it define a frontend */
1871 newpeer->local = 1;
1872
1873 if (!curpeers->peers_fe) {
1874 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1875 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1876 err_code |= ERR_ALERT | ERR_ABORT;
1877 goto out;
1878 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001879
Willy Tarreau237250c2011-07-29 01:49:03 +02001880 init_new_proxy(curpeers->peers_fe);
1881 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001882 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001883 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1884 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01001885 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02001886
1887 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1888
Willy Tarreau902636f2013-03-10 19:44:48 +01001889 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1890 if (errmsg && *errmsg) {
1891 indent_msg(&errmsg, 2);
1892 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001893 }
1894 else
1895 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1896 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001897 err_code |= ERR_FATAL;
1898 goto out;
1899 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001900
1901 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001902 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001903 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1904 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02001905 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02001906 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001907 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01001908 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001909 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1910 global.maxsock += l->maxconn;
1911 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001912 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001913 else {
1914 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1915 file, linenum, args[0], args[1],
1916 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1917 err_code |= ERR_FATAL;
1918 goto out;
1919 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001920 }
1921 } /* neither "peer" nor "peers" */
1922 else if (*args[0] != 0) {
1923 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1924 err_code |= ERR_ALERT | ERR_FATAL;
1925 goto out;
1926 }
1927
1928out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001929 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001930 return err_code;
1931}
1932
Simon Horman0d16a402015-01-30 11:22:58 +09001933
1934/*
1935 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
1936 * Returns the error code, 0 if OK, or any combination of :
1937 * - ERR_ABORT: must abort ASAP
1938 * - ERR_FATAL: we can continue parsing but not start the service
1939 * - ERR_WARN: a warning has been emitted
1940 * - ERR_ALERT: an alert has been emitted
1941 * Only the two first ones can stop processing, the two others are just
1942 * indicators.
1943 */
1944int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
1945{
1946 static struct mailers *curmailers = NULL;
1947 struct mailer *newmailer = NULL;
1948 const char *err;
1949 int err_code = 0;
1950 char *errmsg = NULL;
1951
1952 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
1953 if (!*args[1]) {
1954 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
1955 err_code |= ERR_ALERT | ERR_ABORT;
1956 goto out;
1957 }
1958
1959 err = invalid_char(args[1]);
1960 if (err) {
1961 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1962 file, linenum, *err, args[0], args[1]);
1963 err_code |= ERR_ALERT | ERR_ABORT;
1964 goto out;
1965 }
1966
1967 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
1968 /*
1969 * If there are two proxies with the same name only following
1970 * combinations are allowed:
1971 */
1972 if (strcmp(curmailers->id, args[1]) == 0) {
1973 Warning("Parsing [%s:%d]: mailers '%s' has same name as another mailers (declared at %s:%d).\n",
1974 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
1975 err_code |= ERR_WARN;
1976 }
1977 }
1978
1979 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
1980 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1981 err_code |= ERR_ALERT | ERR_ABORT;
1982 goto out;
1983 }
1984
1985 curmailers->next = mailers;
1986 mailers = curmailers;
1987 curmailers->conf.file = strdup(file);
1988 curmailers->conf.line = linenum;
1989 curmailers->id = strdup(args[1]);
1990 }
1991 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
1992 struct sockaddr_storage *sk;
1993 int port1, port2;
1994 struct protocol *proto;
1995
1996 if (!*args[2]) {
1997 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1998 file, linenum, args[0]);
1999 err_code |= ERR_ALERT | ERR_FATAL;
2000 goto out;
2001 }
2002
2003 err = invalid_char(args[1]);
2004 if (err) {
2005 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2006 file, linenum, *err, args[1]);
2007 err_code |= ERR_ALERT | ERR_FATAL;
2008 goto out;
2009 }
2010
2011 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2012 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2013 err_code |= ERR_ALERT | ERR_ABORT;
2014 goto out;
2015 }
2016
2017 /* the mailers are linked backwards first */
2018 curmailers->count++;
2019 newmailer->next = curmailers->mailer_list;
2020 curmailers->mailer_list = newmailer;
2021 newmailer->mailers = curmailers;
2022 newmailer->conf.file = strdup(file);
2023 newmailer->conf.line = linenum;
2024
2025 newmailer->id = strdup(args[1]);
2026
2027 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2028 if (!sk) {
2029 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2030 err_code |= ERR_ALERT | ERR_FATAL;
2031 goto out;
2032 }
2033
2034 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002035 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2036 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002037 file, linenum, args[0], args[1]);
2038 err_code |= ERR_ALERT | ERR_FATAL;
2039 goto out;
2040 }
2041
2042 if (port1 != port2) {
2043 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2044 file, linenum, args[0], args[1], args[2]);
2045 err_code |= ERR_ALERT | ERR_FATAL;
2046 goto out;
2047 }
2048
2049 if (!port1) {
2050 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2051 file, linenum, args[0], args[1], args[2]);
2052 err_code |= ERR_ALERT | ERR_FATAL;
2053 goto out;
2054 }
2055
2056 newmailer->addr = *sk;
2057 newmailer->proto = proto;
2058 newmailer->xprt = &raw_sock;
2059 newmailer->sock_init_arg = NULL;
2060 } /* neither "mailer" nor "mailers" */
2061 else if (*args[0] != 0) {
2062 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2063 err_code |= ERR_ALERT | ERR_FATAL;
2064 goto out;
2065 }
2066
2067out:
2068 free(errmsg);
2069 return err_code;
2070}
2071
Simon Horman9dc49962015-01-30 11:22:59 +09002072static void free_email_alert(struct proxy *p)
2073{
2074 free(p->email_alert.mailers.name);
2075 p->email_alert.mailers.name = NULL;
2076 free(p->email_alert.from);
2077 p->email_alert.from = NULL;
2078 free(p->email_alert.to);
2079 p->email_alert.to = NULL;
2080 free(p->email_alert.myhostname);
2081 p->email_alert.myhostname = NULL;
2082}
2083
Willy Tarreau3842f002009-06-14 11:39:52 +02002084int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002085{
2086 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002087 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002088 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002089 int rc;
2090 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002091 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002092 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002093 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002094 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002095 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002096
Willy Tarreau977b8e42006-12-29 14:19:17 +01002097 if (!strcmp(args[0], "listen"))
2098 rc = PR_CAP_LISTEN;
2099 else if (!strcmp(args[0], "frontend"))
2100 rc = PR_CAP_FE | PR_CAP_RS;
2101 else if (!strcmp(args[0], "backend"))
2102 rc = PR_CAP_BE | PR_CAP_RS;
2103 else if (!strcmp(args[0], "ruleset"))
2104 rc = PR_CAP_RS;
2105 else
2106 rc = PR_CAP_NONE;
2107
2108 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002109 struct ebpt_node *node;
2110
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111 if (!*args[1]) {
2112 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2113 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2114 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002115 err_code |= ERR_ALERT | ERR_ABORT;
2116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002117 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002118
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002119 err = invalid_char(args[1]);
2120 if (err) {
2121 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2122 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002123 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002124 }
2125
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002126 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
2127 curproxy = container_of(node, struct proxy, conf.by_name);
2128
2129 if (strcmp(curproxy->id, args[1]) != 0)
2130 break;
2131
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002132 /*
2133 * If there are two proxies with the same name only following
2134 * combinations are allowed:
2135 *
2136 * listen backend frontend ruleset
2137 * listen - - - -
2138 * backend - - OK -
2139 * frontend - OK - -
2140 * ruleset - - - -
2141 */
2142
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002143 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
2144 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02002145 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
2146 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2147 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02002148 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002149 }
2150 }
2151
Willy Tarreaubaaee002006-06-26 02:48:02 +02002152 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2153 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002154 err_code |= ERR_ALERT | ERR_ABORT;
2155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002156 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002157
Willy Tarreau97cb7802010-01-03 20:23:58 +01002158 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002159 curproxy->next = proxy;
2160 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002161 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2162 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002163 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002164 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002165 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002166 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002167
2168 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002169 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002170 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02002171
Willy Tarreau4348fad2012-09-20 16:48:07 +02002172 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2173
Willy Tarreau902636f2013-03-10 19:44:48 +01002174 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2175 if (errmsg && *errmsg) {
2176 indent_msg(&errmsg, 2);
2177 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002178 }
2179 else
2180 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2181 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002182 err_code |= ERR_FATAL;
2183 goto out;
2184 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002185
Willy Tarreau4348fad2012-09-20 16:48:07 +02002186 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002187 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002188 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002189 }
2190
2191 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002192 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002193 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002194
Willy Tarreaubaaee002006-06-26 02:48:02 +02002195 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002196 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002197 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002198 curproxy->no_options = defproxy.no_options;
2199 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002200 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002201 curproxy->except_net = defproxy.except_net;
2202 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002203 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002204 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002205
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002206 if (defproxy.fwdfor_hdr_len) {
2207 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2208 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2209 }
2210
Willy Tarreaub86db342009-11-30 11:50:16 +01002211 if (defproxy.orgto_hdr_len) {
2212 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2213 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2214 }
2215
Mark Lamourinec2247f02012-01-04 13:02:01 -05002216 if (defproxy.server_id_hdr_len) {
2217 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2218 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2219 }
2220
Willy Tarreau977b8e42006-12-29 14:19:17 +01002221 if (curproxy->cap & PR_CAP_FE) {
2222 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002223 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002224 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002225
2226 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002227 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2228 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002229
2230 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2231 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002232
Willy Tarreau977b8e42006-12-29 14:19:17 +01002233 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002234 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002235 curproxy->fullconn = defproxy.fullconn;
2236 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002237 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002238
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002239 if (defproxy.check_req) {
2240 curproxy->check_req = calloc(1, defproxy.check_len);
2241 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2242 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002243 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002244
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002245 if (defproxy.expect_str) {
2246 curproxy->expect_str = strdup(defproxy.expect_str);
2247 if (defproxy.expect_regex) {
2248 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002249 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2250 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002251 }
2252 }
2253
Willy Tarreau67402132012-05-31 20:40:20 +02002254 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002255 if (defproxy.cookie_name)
2256 curproxy->cookie_name = strdup(defproxy.cookie_name);
2257 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002258 if (defproxy.cookie_domain)
2259 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002260
Willy Tarreau31936852010-10-06 16:59:56 +02002261 if (defproxy.cookie_maxidle)
2262 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2263
2264 if (defproxy.cookie_maxlife)
2265 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2266
Emeric Brun647caf12009-06-30 17:57:00 +02002267 if (defproxy.rdp_cookie_name)
2268 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2269 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2270
Willy Tarreau01732802007-11-01 22:48:15 +01002271 if (defproxy.url_param_name)
2272 curproxy->url_param_name = strdup(defproxy.url_param_name);
2273 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002274
Benoitaffb4812009-03-25 13:02:10 +01002275 if (defproxy.hh_name)
2276 curproxy->hh_name = strdup(defproxy.hh_name);
2277 curproxy->hh_len = defproxy.hh_len;
2278 curproxy->hh_match_domain = defproxy.hh_match_domain;
2279
Willy Tarreauef9a3602012-12-08 22:29:20 +01002280 if (defproxy.conn_src.iface_name)
2281 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2282 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002283 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002284#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002285 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002286#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002287 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002289 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002290 if (defproxy.capture_name)
2291 curproxy->capture_name = strdup(defproxy.capture_name);
2292 curproxy->capture_namelen = defproxy.capture_namelen;
2293 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002294 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295
Willy Tarreau977b8e42006-12-29 14:19:17 +01002296 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002297 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002298 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002299 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002300 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002301 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002302 curproxy->mon_net = defproxy.mon_net;
2303 curproxy->mon_mask = defproxy.mon_mask;
2304 if (defproxy.monitor_uri)
2305 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2306 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002307 if (defproxy.defbe.name)
2308 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002309
2310 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002311 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2312 if (curproxy->conf.logformat_string &&
2313 curproxy->conf.logformat_string != default_http_log_format &&
2314 curproxy->conf.logformat_string != default_tcp_log_format &&
2315 curproxy->conf.logformat_string != clf_http_log_format)
2316 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2317
2318 if (defproxy.conf.lfs_file) {
2319 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2320 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2321 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002322 }
2323
2324 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002325 curproxy->timeout.connect = defproxy.timeout.connect;
2326 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002327 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002328 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002329 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002330 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002331 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002332 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002333 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002334 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002335 }
2336
Willy Tarreaubaaee002006-06-26 02:48:02 +02002337 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002338 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002339
2340 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002341 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002342 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002343 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002344 LIST_INIT(&node->list);
2345 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2346 }
2347
Willy Tarreau62a61232013-04-12 18:13:46 +02002348 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2349 if (curproxy->conf.uniqueid_format_string)
2350 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2351
Willy Tarreau094af4e2015-01-07 15:03:42 +01002352 if (defproxy.log_tag)
2353 curproxy->log_tag = strdup(defproxy.log_tag);
2354
Willy Tarreau62a61232013-04-12 18:13:46 +02002355 if (defproxy.conf.uif_file) {
2356 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2357 curproxy->conf.uif_line = defproxy.conf.uif_line;
2358 }
William Lallemanda73203e2012-03-12 12:48:57 +01002359
2360 /* copy default header unique id */
2361 if (defproxy.header_unique_id)
2362 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2363
William Lallemand82fe75c2012-10-23 10:25:10 +02002364 /* default compression options */
2365 if (defproxy.comp != NULL) {
2366 curproxy->comp = calloc(1, sizeof(struct comp));
2367 curproxy->comp->algos = defproxy.comp->algos;
2368 curproxy->comp->types = defproxy.comp->types;
2369 }
2370
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002372 curproxy->conf.used_listener_id = EB_ROOT;
2373 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002374
Simon Horman98637e52014-06-20 12:30:16 +09002375 if (defproxy.check_path)
2376 curproxy->check_path = strdup(defproxy.check_path);
2377 if (defproxy.check_command)
2378 curproxy->check_command = strdup(defproxy.check_command);
2379
Simon Horman9dc49962015-01-30 11:22:59 +09002380 if (defproxy.email_alert.mailers.name)
2381 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2382 if (defproxy.email_alert.from)
2383 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2384 if (defproxy.email_alert.to)
2385 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2386 if (defproxy.email_alert.myhostname)
2387 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002388 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002389
Willy Tarreau93893792009-07-23 13:19:11 +02002390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 }
2392 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2393 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002394 /* FIXME-20070101: we should do this too at the end of the
2395 * config parsing to free all default values.
2396 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002397 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002398 free(defproxy.check_command);
2399 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002400 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002401 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002402 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002403 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002404 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002405 free(defproxy.capture_name);
2406 free(defproxy.monitor_uri);
2407 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002408 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002409 free(defproxy.fwdfor_hdr_name);
2410 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002411 free(defproxy.orgto_hdr_name);
2412 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002413 free(defproxy.server_id_hdr_name);
2414 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002415 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002416 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002417 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002418 free(defproxy.expect_regex);
2419 defproxy.expect_regex = NULL;
2420 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002421
Willy Tarreau62a61232013-04-12 18:13:46 +02002422 if (defproxy.conf.logformat_string != default_http_log_format &&
2423 defproxy.conf.logformat_string != default_tcp_log_format &&
2424 defproxy.conf.logformat_string != clf_http_log_format)
2425 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002426
Willy Tarreau62a61232013-04-12 18:13:46 +02002427 free(defproxy.conf.uniqueid_format_string);
2428 free(defproxy.conf.lfs_file);
2429 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002430 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002431 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002432
Willy Tarreaua534fea2008-08-03 12:19:50 +02002433 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002434 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002435
Willy Tarreaubaaee002006-06-26 02:48:02 +02002436 /* we cannot free uri_auth because it might already be used */
2437 init_default_instance();
2438 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002439 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2440 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002441 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002442 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443 }
2444 else if (curproxy == NULL) {
2445 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002446 err_code |= ERR_ALERT | ERR_FATAL;
2447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002449
2450 /* update the current file and line being parsed */
2451 curproxy->conf.args.file = curproxy->conf.file;
2452 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002453
2454 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002455 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2456 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2457 if (err_code & ERR_FATAL)
2458 goto out;
2459 }
2460 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002461 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002462 int cur_arg;
2463
Willy Tarreaubaaee002006-06-26 02:48:02 +02002464 if (curproxy == &defproxy) {
2465 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002468 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002469 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002470 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471
Willy Tarreau24709282013-03-10 21:32:12 +01002472 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002473 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002474 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002478
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002479 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002480
2481 /* use default settings for unix sockets */
2482 bind_conf->ux.uid = global.unix_bind.ux.uid;
2483 bind_conf->ux.gid = global.unix_bind.ux.gid;
2484 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002485
2486 /* NOTE: the following line might create several listeners if there
2487 * are comma-separated IPs or port ranges. So all further processing
2488 * will have to be applied to all listeners created after last_listen.
2489 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002490 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2491 if (errmsg && *errmsg) {
2492 indent_msg(&errmsg, 2);
2493 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002494 }
2495 else
2496 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2497 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002498 err_code |= ERR_ALERT | ERR_FATAL;
2499 goto out;
2500 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002501
Willy Tarreau4348fad2012-09-20 16:48:07 +02002502 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2503 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002504 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002505 }
2506
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002507 cur_arg = 2;
2508 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002509 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002510 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002511 char *err;
2512
Willy Tarreau26982662012-09-12 23:17:10 +02002513 kw = bind_find_kw(args[cur_arg]);
2514 if (kw) {
2515 char *err = NULL;
2516 int code;
2517
2518 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002519 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2520 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002521 cur_arg += 1 + kw->skip ;
2522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
2524 }
2525
Willy Tarreau4348fad2012-09-20 16:48:07 +02002526 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002527 err_code |= code;
2528
2529 if (code) {
2530 if (err && *err) {
2531 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002532 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002533 }
2534 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002535 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2536 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002537 if (code & ERR_FATAL) {
2538 free(err);
2539 cur_arg += 1 + kw->skip;
2540 goto out;
2541 }
2542 }
2543 free(err);
2544 cur_arg += 1 + kw->skip;
2545 continue;
2546 }
2547
Willy Tarreau8638f482012-09-18 18:01:17 +02002548 err = NULL;
2549 if (!bind_dumped) {
2550 bind_dump_kws(&err);
2551 indent_msg(&err, 4);
2552 bind_dumped = 1;
2553 }
2554
2555 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2556 file, linenum, args[0], args[1], args[cur_arg],
2557 err ? " Registered keywords :" : "", err ? err : "");
2558 free(err);
2559
Willy Tarreau93893792009-07-23 13:19:11 +02002560 err_code |= ERR_ALERT | ERR_FATAL;
2561 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002562 }
Willy Tarreau93893792009-07-23 13:19:11 +02002563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 }
2565 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002566 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2568 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_ALERT | ERR_FATAL;
2570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002572 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002573 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002574
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 /* flush useless bits */
2576 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002579 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002580 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002581 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002582
Willy Tarreau1c47f852006-07-09 08:22:27 +02002583 if (!*args[1]) {
2584 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2585 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002588 }
2589
Willy Tarreaua534fea2008-08-03 12:19:50 +02002590 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002591 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002592 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002593 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002594 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2595
Willy Tarreau93893792009-07-23 13:19:11 +02002596 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002597 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2599 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2600 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2601 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2602 else {
2603 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002604 err_code |= ERR_ALERT | ERR_FATAL;
2605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002606 }
2607 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002608 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002609 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002610
2611 if (curproxy == &defproxy) {
2612 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2613 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002616 }
2617
2618 if (!*args[1]) {
2619 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2620 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002621 err_code |= ERR_ALERT | ERR_FATAL;
2622 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002623 }
2624
2625 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002626 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002627
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002628 if (curproxy->uuid <= 0) {
2629 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002630 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002631 err_code |= ERR_ALERT | ERR_FATAL;
2632 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002633 }
2634
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002635 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2636 if (node) {
2637 struct proxy *target = container_of(node, struct proxy, conf.id);
2638 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2639 file, linenum, proxy_type_str(curproxy), curproxy->id,
2640 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
2643 }
2644 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002645 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002646 else if (!strcmp(args[0], "description")) {
2647 int i, len=0;
2648 char *d;
2649
Cyril Bonté99ed3272010-01-24 23:29:44 +01002650 if (curproxy == &defproxy) {
2651 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2652 file, linenum, args[0]);
2653 err_code |= ERR_ALERT | ERR_FATAL;
2654 goto out;
2655 }
2656
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002657 if (!*args[1]) {
2658 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2659 file, linenum, args[0]);
2660 return -1;
2661 }
2662
Willy Tarreau348acfe2014-04-14 15:00:39 +02002663 for (i = 1; *args[i]; i++)
2664 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002665
2666 d = (char *)calloc(1, len);
2667 curproxy->desc = d;
2668
Willy Tarreau348acfe2014-04-14 15:00:39 +02002669 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2670 for (i = 2; *args[i]; i++)
2671 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002672
2673 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002674 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2675 curproxy->state = PR_STSTOPPED;
2676 }
2677 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2678 curproxy->state = PR_STNEW;
2679 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002680 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2681 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002682 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002683
2684 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002685 unsigned int low, high;
2686
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002687 if (strcmp(args[cur_arg], "all") == 0) {
2688 set = 0;
2689 break;
2690 }
2691 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002692 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002693 }
2694 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002695 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002696 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002697 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002698 char *dash = strchr(args[cur_arg], '-');
2699
2700 low = high = str2uic(args[cur_arg]);
2701 if (dash)
2702 high = str2uic(dash + 1);
2703
2704 if (high < low) {
2705 unsigned int swap = low;
2706 low = high;
2707 high = swap;
2708 }
2709
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002710 if (low < 1 || high > LONGBITS) {
2711 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2712 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002713 err_code |= ERR_ALERT | ERR_FATAL;
2714 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002715 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002716 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002717 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002718 }
2719 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002720 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2721 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002722 err_code |= ERR_ALERT | ERR_FATAL;
2723 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002724 }
2725 cur_arg++;
2726 }
2727 curproxy->bind_proc = set;
2728 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002729 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002730 if (curproxy == &defproxy) {
2731 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002732 err_code |= ERR_ALERT | ERR_FATAL;
2733 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002734 }
2735
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002736 err = invalid_char(args[1]);
2737 if (err) {
2738 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2739 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002740 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002741 }
2742
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002743 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002744 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2745 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002746 err_code |= ERR_ALERT | ERR_FATAL;
2747 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002748 }
2749 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002750 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2751 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002752
Willy Tarreau977b8e42006-12-29 14:19:17 +01002753 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002754 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002755
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 if (*(args[1]) == 0) {
2757 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2758 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002759 err_code |= ERR_ALERT | ERR_FATAL;
2760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002761 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002762
Willy Tarreau67402132012-05-31 20:40:20 +02002763 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002764 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002765 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002766 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002767 curproxy->cookie_name = strdup(args[1]);
2768 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002769
Willy Tarreaubaaee002006-06-26 02:48:02 +02002770 cur_arg = 2;
2771 while (*(args[cur_arg])) {
2772 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002773 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002774 }
2775 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002776 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002777 }
2778 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002779 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002780 }
2781 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002782 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002783 }
2784 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002785 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002786 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002787 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002788 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002789 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002790 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002791 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002792 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002793 else if (!strcmp(args[cur_arg], "httponly")) {
2794 curproxy->ck_opts |= PR_CK_HTTPONLY;
2795 }
2796 else if (!strcmp(args[cur_arg], "secure")) {
2797 curproxy->ck_opts |= PR_CK_SECURE;
2798 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002799 else if (!strcmp(args[cur_arg], "domain")) {
2800 if (!*args[cur_arg + 1]) {
2801 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2802 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002803 err_code |= ERR_ALERT | ERR_FATAL;
2804 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002805 }
2806
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002807 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002808 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002809 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2810 " dots nor does not start with a dot."
2811 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002812 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002813 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002814 }
2815
2816 err = invalid_domainchar(args[cur_arg + 1]);
2817 if (err) {
2818 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2819 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002822 }
2823
Willy Tarreau68a897b2009-12-03 23:28:34 +01002824 if (!curproxy->cookie_domain) {
2825 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2826 } else {
2827 /* one domain was already specified, add another one by
2828 * building the string which will be returned along with
2829 * the cookie.
2830 */
2831 char *new_ptr;
2832 int new_len = strlen(curproxy->cookie_domain) +
2833 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2834 new_ptr = malloc(new_len);
2835 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2836 free(curproxy->cookie_domain);
2837 curproxy->cookie_domain = new_ptr;
2838 }
Willy Tarreau31936852010-10-06 16:59:56 +02002839 cur_arg++;
2840 }
2841 else if (!strcmp(args[cur_arg], "maxidle")) {
2842 unsigned int maxidle;
2843 const char *res;
2844
2845 if (!*args[cur_arg + 1]) {
2846 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2847 file, linenum, args[cur_arg]);
2848 err_code |= ERR_ALERT | ERR_FATAL;
2849 goto out;
2850 }
2851
2852 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2853 if (res) {
2854 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2855 file, linenum, *res, args[cur_arg]);
2856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
2858 }
2859 curproxy->cookie_maxidle = maxidle;
2860 cur_arg++;
2861 }
2862 else if (!strcmp(args[cur_arg], "maxlife")) {
2863 unsigned int maxlife;
2864 const char *res;
2865
2866 if (!*args[cur_arg + 1]) {
2867 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2868 file, linenum, args[cur_arg]);
2869 err_code |= ERR_ALERT | ERR_FATAL;
2870 goto out;
2871 }
2872
2873 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2874 if (res) {
2875 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2876 file, linenum, *res, args[cur_arg]);
2877 err_code |= ERR_ALERT | ERR_FATAL;
2878 goto out;
2879 }
2880 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002881 cur_arg++;
2882 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002883 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002884 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 +02002885 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002886 err_code |= ERR_ALERT | ERR_FATAL;
2887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002888 }
2889 cur_arg++;
2890 }
Willy Tarreau67402132012-05-31 20:40:20 +02002891 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002892 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2893 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002894 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002895 }
2896
Willy Tarreau67402132012-05-31 20:40:20 +02002897 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002898 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2899 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002900 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002901 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002902
Willy Tarreau67402132012-05-31 20:40:20 +02002903 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002904 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2905 file, linenum);
2906 err_code |= ERR_ALERT | ERR_FATAL;
2907 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002908 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09002909 else if (!strcmp(args[0], "email-alert")) {
2910 if (*(args[1]) == 0) {
2911 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2912 file, linenum, args[0]);
2913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
2915 }
2916
2917 if (!strcmp(args[1], "from")) {
2918 if (*(args[1]) == 0) {
2919 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2920 file, linenum, args[1]);
2921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
2923 }
2924 free(curproxy->email_alert.from);
2925 curproxy->email_alert.from = strdup(args[2]);
2926 }
2927 else if (!strcmp(args[1], "mailers")) {
2928 if (*(args[1]) == 0) {
2929 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2930 file, linenum, args[1]);
2931 err_code |= ERR_ALERT | ERR_FATAL;
2932 goto out;
2933 }
2934 free(curproxy->email_alert.mailers.name);
2935 curproxy->email_alert.mailers.name = strdup(args[2]);
2936 }
2937 else if (!strcmp(args[1], "myhostname")) {
2938 if (*(args[1]) == 0) {
2939 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2940 file, linenum, args[1]);
2941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
2943 }
2944 free(curproxy->email_alert.myhostname);
2945 curproxy->email_alert.myhostname = strdup(args[2]);
2946 }
Simon Horman64e34162015-02-06 11:11:57 +09002947 else if (!strcmp(args[1], "level")) {
2948 curproxy->email_alert.level = get_log_level(args[2]);
2949 if (curproxy->email_alert.level < 0) {
2950 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
2951 file, linenum, args[1], args[2]);
2952 err_code |= ERR_ALERT | ERR_FATAL;
2953 goto out;
2954 }
2955 }
Simon Horman9dc49962015-01-30 11:22:59 +09002956 else if (!strcmp(args[1], "to")) {
2957 if (*(args[1]) == 0) {
2958 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2959 file, linenum, args[1]);
2960 err_code |= ERR_ALERT | ERR_FATAL;
2961 goto out;
2962 }
2963 free(curproxy->email_alert.to);
2964 curproxy->email_alert.to = strdup(args[2]);
2965 }
2966 else {
2967 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
2968 file, linenum, args[1]);
2969 err_code |= ERR_ALERT | ERR_FATAL;
2970 goto out;
2971 }
Simon Horman64e34162015-02-06 11:11:57 +09002972 /* Indicate that the email_alert is at least partially configured */
2973 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09002974 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09002975 else if (!strcmp(args[0], "external-check")) {
2976 if (*(args[1]) == 0) {
2977 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2978 file, linenum, args[0]);
2979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
2981 }
2982
2983 if (!strcmp(args[1], "command")) {
2984 if (*(args[1]) == 0) {
2985 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2986 file, linenum, args[1]);
2987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
2989 }
2990 free(curproxy->check_command);
2991 curproxy->check_command = strdup(args[2]);
2992 }
2993 else if (!strcmp(args[1], "path")) {
2994 if (*(args[1]) == 0) {
2995 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2996 file, linenum, args[1]);
2997 err_code |= ERR_ALERT | ERR_FATAL;
2998 goto out;
2999 }
3000 free(curproxy->check_path);
3001 curproxy->check_path = strdup(args[2]);
3002 }
3003 else {
3004 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3005 file, linenum, args[1]);
3006 err_code |= ERR_ALERT | ERR_FATAL;
3007 goto out;
3008 }
3009 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003010 else if (!strcmp(args[0], "persist")) { /* persist */
3011 if (*(args[1]) == 0) {
3012 Alert("parsing [%s:%d] : missing persist method.\n",
3013 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003016 }
3017
3018 if (!strncmp(args[1], "rdp-cookie", 10)) {
3019 curproxy->options2 |= PR_O2_RDPC_PRST;
3020
Emeric Brunb982a3d2010-01-04 15:45:53 +01003021 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003022 const char *beg, *end;
3023
3024 beg = args[1] + 11;
3025 end = strchr(beg, ')');
3026
3027 if (!end || end == beg) {
3028 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3029 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003032 }
3033
3034 free(curproxy->rdp_cookie_name);
3035 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3036 curproxy->rdp_cookie_len = end-beg;
3037 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003038 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003039 free(curproxy->rdp_cookie_name);
3040 curproxy->rdp_cookie_name = strdup("msts");
3041 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3042 }
3043 else { /* syntax */
3044 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3045 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003046 err_code |= ERR_ALERT | ERR_FATAL;
3047 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003048 }
3049 }
3050 else {
3051 Alert("parsing [%s:%d] : unknown persist method.\n",
3052 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003053 err_code |= ERR_ALERT | ERR_FATAL;
3054 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003055 }
3056 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003057 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003058 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003059
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003060 if (curproxy == &defproxy) {
3061 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3062 err_code |= ERR_ALERT | ERR_FATAL;
3063 goto out;
3064 }
3065
Willy Tarreau977b8e42006-12-29 14:19:17 +01003066 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003067 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003068
Willy Tarreaubaaee002006-06-26 02:48:02 +02003069 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003070 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003071 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003074 }
3075 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003076 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003077 curproxy->appsession_name = strdup(args[1]);
3078 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3079 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003080 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3081 if (err) {
3082 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3083 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003084 err_code |= ERR_ALERT | ERR_FATAL;
3085 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003086 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003087 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003088
Willy Tarreau51041c72007-09-09 21:56:53 +02003089 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3090 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003091 err_code |= ERR_ALERT | ERR_ABORT;
3092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003093 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003094
3095 cur_arg = 6;
3096 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003097 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3098 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003099 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003100 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003101 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003102 } else if (!strcmp(args[cur_arg], "prefix")) {
3103 curproxy->options2 |= PR_O2_AS_PFX;
3104 } else if (!strcmp(args[cur_arg], "mode")) {
3105 if (!*args[cur_arg + 1]) {
3106 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3107 file, linenum, args[0], args[cur_arg]);
3108 err_code |= ERR_ALERT | ERR_FATAL;
3109 goto out;
3110 }
3111
3112 cur_arg++;
3113 if (!strcmp(args[cur_arg], "query-string")) {
3114 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3115 curproxy->options2 |= PR_O2_AS_M_QS;
3116 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3117 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3118 curproxy->options2 |= PR_O2_AS_M_PP;
3119 } else {
3120 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3121 err_code |= ERR_ALERT | ERR_FATAL;
3122 goto out;
3123 }
3124 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003125 cur_arg++;
3126 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003127 } /* Url App Session */
3128 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003129 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003130 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003131
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003133 if (curproxy == &defproxy) {
3134 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3135 err_code |= ERR_ALERT | ERR_FATAL;
3136 goto out;
3137 }
3138
Willy Tarreaubaaee002006-06-26 02:48:02 +02003139 if (*(args[4]) == 0) {
3140 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3141 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003142 err_code |= ERR_ALERT | ERR_FATAL;
3143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003144 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003145 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003146 curproxy->capture_name = strdup(args[2]);
3147 curproxy->capture_namelen = strlen(curproxy->capture_name);
3148 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003149 curproxy->to_log |= LW_COOKIE;
3150 }
3151 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3152 struct cap_hdr *hdr;
3153
3154 if (curproxy == &defproxy) {
3155 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 +02003156 err_code |= ERR_ALERT | ERR_FATAL;
3157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 }
3159
3160 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3161 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3162 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003165 }
3166
3167 hdr = calloc(sizeof(struct cap_hdr), 1);
3168 hdr->next = curproxy->req_cap;
3169 hdr->name = strdup(args[3]);
3170 hdr->namelen = strlen(args[3]);
3171 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003172 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 hdr->index = curproxy->nb_req_cap++;
3174 curproxy->req_cap = hdr;
3175 curproxy->to_log |= LW_REQHDR;
3176 }
3177 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3178 struct cap_hdr *hdr;
3179
3180 if (curproxy == &defproxy) {
3181 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 +02003182 err_code |= ERR_ALERT | ERR_FATAL;
3183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 }
3185
3186 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3187 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3188 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003191 }
3192 hdr = calloc(sizeof(struct cap_hdr), 1);
3193 hdr->next = curproxy->rsp_cap;
3194 hdr->name = strdup(args[3]);
3195 hdr->namelen = strlen(args[3]);
3196 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003197 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 hdr->index = curproxy->nb_rsp_cap++;
3199 curproxy->rsp_cap = hdr;
3200 curproxy->to_log |= LW_RSPHDR;
3201 }
3202 else {
3203 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3204 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 }
3208 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003210 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003211 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003212
Willy Tarreaubaaee002006-06-26 02:48:02 +02003213 if (*(args[1]) == 0) {
3214 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3215 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003218 }
3219 curproxy->conn_retries = atol(args[1]);
3220 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003221 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003222 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003223
3224 if (curproxy == &defproxy) {
3225 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3226 err_code |= ERR_ALERT | ERR_FATAL;
3227 goto out;
3228 }
3229
Willy Tarreau20b0de52012-12-24 15:45:22 +01003230 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3231 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3232 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3233 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003234 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003235 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3236 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 +01003237 file, linenum, args[0]);
3238 err_code |= ERR_WARN;
3239 }
3240
Willy Tarreauff011f22011-01-06 17:51:27 +01003241 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003242
Willy Tarreauff011f22011-01-06 17:51:27 +01003243 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003244 err_code |= ERR_ALERT | ERR_ABORT;
3245 goto out;
3246 }
3247
Willy Tarreau5002f572014-04-23 01:32:02 +02003248 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003249 err_code |= warnif_cond_conflicts(rule->cond,
3250 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3251 file, linenum);
3252
Willy Tarreauff011f22011-01-06 17:51:27 +01003253 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003254 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003255 else if (!strcmp(args[0], "http-response")) { /* response access control */
3256 struct http_res_rule *rule;
3257
3258 if (curproxy == &defproxy) {
3259 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3260 err_code |= ERR_ALERT | ERR_FATAL;
3261 goto out;
3262 }
3263
3264 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3265 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3266 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3267 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3268 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3269 file, linenum, args[0]);
3270 err_code |= ERR_WARN;
3271 }
3272
3273 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3274
3275 if (!rule) {
3276 err_code |= ERR_ALERT | ERR_ABORT;
3277 goto out;
3278 }
3279
3280 err_code |= warnif_cond_conflicts(rule->cond,
3281 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3282 file, linenum);
3283
3284 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3285 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003286 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3287 /* set the header name and length into the proxy structure */
3288 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3289 err_code |= ERR_WARN;
3290
3291 if (!*args[1]) {
3292 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3293 file, linenum, args[0]);
3294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
3296 }
3297
3298 /* set the desired header name */
3299 free(curproxy->server_id_hdr_name);
3300 curproxy->server_id_hdr_name = strdup(args[1]);
3301 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3302 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003303 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003304 struct http_req_rule *rule;
3305
Willy Tarreaub099aca2008-10-12 17:26:37 +02003306 if (curproxy == &defproxy) {
3307 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_ALERT | ERR_FATAL;
3309 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003310 }
3311
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003312 /* emulate "block" using "http-request block". Since these rules are supposed to
3313 * be processed before all http-request rules, we put them into their own list
3314 * and will insert them at the end.
3315 */
3316 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3317 if (!rule) {
3318 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003319 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003320 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003321 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3322 err_code |= warnif_cond_conflicts(rule->cond,
3323 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3324 file, linenum);
3325 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003326
3327 if (!already_warned(WARN_BLOCK_DEPRECATED))
3328 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]);
3329
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003330 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003331 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003332 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003333
Cyril Bonté99ed3272010-01-24 23:29:44 +01003334 if (curproxy == &defproxy) {
3335 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3336 err_code |= ERR_ALERT | ERR_FATAL;
3337 goto out;
3338 }
3339
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003340 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003341 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3342 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003343 err_code |= ERR_ALERT | ERR_FATAL;
3344 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003345 }
3346
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003347 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003348 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003349 err_code |= warnif_cond_conflicts(rule->cond,
3350 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3351 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003352 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003353 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003354 struct switching_rule *rule;
3355
Willy Tarreaub099aca2008-10-12 17:26:37 +02003356 if (curproxy == &defproxy) {
3357 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003358 err_code |= ERR_ALERT | ERR_FATAL;
3359 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003360 }
3361
Willy Tarreau55ea7572007-06-17 19:56:27 +02003362 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003363 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003364
3365 if (*(args[1]) == 0) {
3366 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003367 err_code |= ERR_ALERT | ERR_FATAL;
3368 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003369 }
3370
Willy Tarreauf51658d2014-04-23 01:21:56 +02003371 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3372 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3373 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3374 file, linenum, errmsg);
3375 err_code |= ERR_ALERT | ERR_FATAL;
3376 goto out;
3377 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003378
Willy Tarreauf51658d2014-04-23 01:21:56 +02003379 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003380 }
3381
3382 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3383 rule->cond = cond;
3384 rule->be.name = strdup(args[1]);
3385 LIST_INIT(&rule->list);
3386 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3387 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003388 else if (strcmp(args[0], "use-server") == 0) {
3389 struct server_rule *rule;
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
3400 if (*(args[1]) == 0) {
3401 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3402 err_code |= ERR_ALERT | ERR_FATAL;
3403 goto out;
3404 }
3405
3406 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3407 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3408 file, linenum, args[0]);
3409 err_code |= ERR_ALERT | ERR_FATAL;
3410 goto out;
3411 }
3412
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003413 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3414 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3415 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003416 err_code |= ERR_ALERT | ERR_FATAL;
3417 goto out;
3418 }
3419
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003420 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003421
3422 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3423 rule->cond = cond;
3424 rule->srv.name = strdup(args[1]);
3425 LIST_INIT(&rule->list);
3426 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3427 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3428 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003429 else if ((!strcmp(args[0], "force-persist")) ||
3430 (!strcmp(args[0], "ignore-persist"))) {
3431 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003432
3433 if (curproxy == &defproxy) {
3434 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3435 err_code |= ERR_ALERT | ERR_FATAL;
3436 goto out;
3437 }
3438
3439 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3440 err_code |= ERR_WARN;
3441
Willy Tarreauef6494c2010-01-28 17:12:36 +01003442 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003443 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3444 file, linenum, args[0]);
3445 err_code |= ERR_ALERT | ERR_FATAL;
3446 goto out;
3447 }
3448
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003449 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3450 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3451 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003452 err_code |= ERR_ALERT | ERR_FATAL;
3453 goto out;
3454 }
3455
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003456 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3457 * where force-persist is applied.
3458 */
3459 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003460
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003461 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003462 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003463 if (!strcmp(args[0], "force-persist")) {
3464 rule->type = PERSIST_TYPE_FORCE;
3465 } else {
3466 rule->type = PERSIST_TYPE_IGNORE;
3467 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003468 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003469 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003470 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003471 else if (!strcmp(args[0], "stick-table")) {
3472 int myidx = 1;
3473
Emeric Brun32da3c42010-09-23 18:39:19 +02003474 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003475 curproxy->table.type = (unsigned int)-1;
3476 while (*args[myidx]) {
3477 const char *err;
3478
3479 if (strcmp(args[myidx], "size") == 0) {
3480 myidx++;
3481 if (!*(args[myidx])) {
3482 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3483 file, linenum, args[myidx-1]);
3484 err_code |= ERR_ALERT | ERR_FATAL;
3485 goto out;
3486 }
3487 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3488 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3489 file, linenum, *err, args[myidx-1]);
3490 err_code |= ERR_ALERT | ERR_FATAL;
3491 goto out;
3492 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003493 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003494 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003495 else if (strcmp(args[myidx], "peers") == 0) {
3496 myidx++;
Godbach50523162013-12-11 19:48:57 +08003497 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003498 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3499 file, linenum, args[myidx-1]);
3500 err_code |= ERR_ALERT | ERR_FATAL;
3501 goto out;
Godbach50523162013-12-11 19:48:57 +08003502 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003503 curproxy->table.peers.name = strdup(args[myidx++]);
3504 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003505 else if (strcmp(args[myidx], "expire") == 0) {
3506 myidx++;
3507 if (!*(args[myidx])) {
3508 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3509 file, linenum, args[myidx-1]);
3510 err_code |= ERR_ALERT | ERR_FATAL;
3511 goto out;
3512 }
3513 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3514 if (err) {
3515 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3516 file, linenum, *err, args[myidx-1]);
3517 err_code |= ERR_ALERT | ERR_FATAL;
3518 goto out;
3519 }
3520 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003521 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003522 }
3523 else if (strcmp(args[myidx], "nopurge") == 0) {
3524 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003525 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003526 }
3527 else if (strcmp(args[myidx], "type") == 0) {
3528 myidx++;
3529 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3530 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3531 file, linenum, args[myidx]);
3532 err_code |= ERR_ALERT | ERR_FATAL;
3533 goto out;
3534 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003535 /* myidx already points to next arg */
3536 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003537 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003538 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003539 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003540
3541 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003542 nw = args[myidx];
3543 while (*nw) {
3544 /* the "store" keyword supports a comma-separated list */
3545 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003546 sa = NULL; /* store arg */
3547 while (*nw && *nw != ',') {
3548 if (*nw == '(') {
3549 *nw = 0;
3550 sa = ++nw;
3551 while (*nw != ')') {
3552 if (!*nw) {
3553 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3554 file, linenum, args[0], cw);
3555 err_code |= ERR_ALERT | ERR_FATAL;
3556 goto out;
3557 }
3558 nw++;
3559 }
3560 *nw = '\0';
3561 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003562 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003563 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003564 if (*nw)
3565 *nw++ = '\0';
3566 type = stktable_get_data_type(cw);
3567 if (type < 0) {
3568 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3569 file, linenum, args[0], cw);
3570 err_code |= ERR_ALERT | ERR_FATAL;
3571 goto out;
3572 }
Willy Tarreauac782882010-06-20 10:41:54 +02003573
3574 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3575 switch (err) {
3576 case PE_NONE: break;
3577 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003578 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3579 file, linenum, args[0], cw);
3580 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003581 break;
3582
3583 case PE_ARG_MISSING:
3584 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3585 file, linenum, args[0], cw);
3586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
3588
3589 case PE_ARG_NOT_USED:
3590 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3591 file, linenum, args[0], cw);
3592 err_code |= ERR_ALERT | ERR_FATAL;
3593 goto out;
3594
3595 default:
3596 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3597 file, linenum, args[0], cw);
3598 err_code |= ERR_ALERT | ERR_FATAL;
3599 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003600 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003601 }
3602 myidx++;
3603 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003604 else {
3605 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3606 file, linenum, args[myidx]);
3607 err_code |= ERR_ALERT | ERR_FATAL;
3608 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003609 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003610 }
3611
3612 if (!curproxy->table.size) {
3613 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3614 file, linenum);
3615 err_code |= ERR_ALERT | ERR_FATAL;
3616 goto out;
3617 }
3618
3619 if (curproxy->table.type == (unsigned int)-1) {
3620 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3621 file, linenum);
3622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
3624 }
3625 }
3626 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003627 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003628 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003629 int myidx = 0;
3630 const char *name = NULL;
3631 int flags;
3632
3633 if (curproxy == &defproxy) {
3634 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3635 err_code |= ERR_ALERT | ERR_FATAL;
3636 goto out;
3637 }
3638
3639 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3640 err_code |= ERR_WARN;
3641 goto out;
3642 }
3643
3644 myidx++;
3645 if ((strcmp(args[myidx], "store") == 0) ||
3646 (strcmp(args[myidx], "store-request") == 0)) {
3647 myidx++;
3648 flags = STK_IS_STORE;
3649 }
3650 else if (strcmp(args[myidx], "store-response") == 0) {
3651 myidx++;
3652 flags = STK_IS_STORE | STK_ON_RSP;
3653 }
3654 else if (strcmp(args[myidx], "match") == 0) {
3655 myidx++;
3656 flags = STK_IS_MATCH;
3657 }
3658 else if (strcmp(args[myidx], "on") == 0) {
3659 myidx++;
3660 flags = STK_IS_MATCH | STK_IS_STORE;
3661 }
3662 else {
3663 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3664 err_code |= ERR_ALERT | ERR_FATAL;
3665 goto out;
3666 }
3667
3668 if (*(args[myidx]) == 0) {
3669 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3670 err_code |= ERR_ALERT | ERR_FATAL;
3671 goto out;
3672 }
3673
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003674 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003675 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003676 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003677 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003678 err_code |= ERR_ALERT | ERR_FATAL;
3679 goto out;
3680 }
3681
3682 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003683 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3684 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3685 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003686 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003687 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003688 goto out;
3689 }
3690 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003691 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3692 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3693 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003694 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003695 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003696 goto out;
3697 }
3698 }
3699
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003700 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003701 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003702
Emeric Brunb982a3d2010-01-04 15:45:53 +01003703 if (strcmp(args[myidx], "table") == 0) {
3704 myidx++;
3705 name = args[myidx++];
3706 }
3707
Willy Tarreauef6494c2010-01-28 17:12:36 +01003708 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003709 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3710 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3711 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003712 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003713 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003714 goto out;
3715 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003716 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003717 else if (*(args[myidx])) {
3718 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3719 file, linenum, args[0], args[myidx]);
3720 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003721 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003722 goto out;
3723 }
Emeric Brun97679e72010-09-23 17:56:44 +02003724 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003725 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003726 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003727 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003728
Emeric Brunb982a3d2010-01-04 15:45:53 +01003729 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3730 rule->cond = cond;
3731 rule->expr = expr;
3732 rule->flags = flags;
3733 rule->table.name = name ? strdup(name) : NULL;
3734 LIST_INIT(&rule->list);
3735 if (flags & STK_ON_RSP)
3736 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3737 else
3738 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3739 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003740 else if (!strcmp(args[0], "stats")) {
3741 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3742 curproxy->uri_auth = NULL; /* we must detach from the default config */
3743
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003744 if (!*args[1]) {
3745 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003746 } else if (!strcmp(args[1], "admin")) {
3747 struct stats_admin_rule *rule;
3748
3749 if (curproxy == &defproxy) {
3750 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3751 err_code |= ERR_ALERT | ERR_FATAL;
3752 goto out;
3753 }
3754
3755 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3756 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3757 err_code |= ERR_ALERT | ERR_ABORT;
3758 goto out;
3759 }
3760
3761 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3762 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3763 file, linenum, args[0], args[1]);
3764 err_code |= ERR_ALERT | ERR_FATAL;
3765 goto out;
3766 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003767 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3768 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3769 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003770 err_code |= ERR_ALERT | ERR_FATAL;
3771 goto out;
3772 }
3773
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003774 err_code |= warnif_cond_conflicts(cond,
3775 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3776 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003777
3778 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3779 rule->cond = cond;
3780 LIST_INIT(&rule->list);
3781 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003782 } else if (!strcmp(args[1], "uri")) {
3783 if (*(args[2]) == 0) {
3784 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003787 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3788 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003789 err_code |= ERR_ALERT | ERR_ABORT;
3790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003791 }
3792 } else if (!strcmp(args[1], "realm")) {
3793 if (*(args[2]) == 0) {
3794 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003795 err_code |= ERR_ALERT | ERR_FATAL;
3796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003797 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3798 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003799 err_code |= ERR_ALERT | ERR_ABORT;
3800 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003801 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003802 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003803 unsigned interval;
3804
3805 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3806 if (err) {
3807 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3808 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003809 err_code |= ERR_ALERT | ERR_FATAL;
3810 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003811 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3812 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003813 err_code |= ERR_ALERT | ERR_ABORT;
3814 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003815 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003816 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003817 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003818
3819 if (curproxy == &defproxy) {
3820 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
3823 }
3824
3825 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3826 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3827 err_code |= ERR_ALERT | ERR_ABORT;
3828 goto out;
3829 }
3830
Willy Tarreauff011f22011-01-06 17:51:27 +01003831 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3832 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003833 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3834 file, linenum, args[0]);
3835 err_code |= ERR_WARN;
3836 }
3837
Willy Tarreauff011f22011-01-06 17:51:27 +01003838 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003839
Willy Tarreauff011f22011-01-06 17:51:27 +01003840 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003841 err_code |= ERR_ALERT | ERR_ABORT;
3842 goto out;
3843 }
3844
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003845 err_code |= warnif_cond_conflicts(rule->cond,
3846 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3847 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003848 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003849
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 } else if (!strcmp(args[1], "auth")) {
3851 if (*(args[2]) == 0) {
3852 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003853 err_code |= ERR_ALERT | ERR_FATAL;
3854 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003855 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3856 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003857 err_code |= ERR_ALERT | ERR_ABORT;
3858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 }
3860 } else if (!strcmp(args[1], "scope")) {
3861 if (*(args[2]) == 0) {
3862 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003863 err_code |= ERR_ALERT | ERR_FATAL;
3864 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003865 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3866 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003867 err_code |= ERR_ALERT | ERR_ABORT;
3868 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003869 }
3870 } else if (!strcmp(args[1], "enable")) {
3871 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3872 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003873 err_code |= ERR_ALERT | ERR_ABORT;
3874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003875 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003876 } else if (!strcmp(args[1], "hide-version")) {
3877 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3878 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003879 err_code |= ERR_ALERT | ERR_ABORT;
3880 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003881 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003882 } else if (!strcmp(args[1], "show-legends")) {
3883 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3884 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3885 err_code |= ERR_ALERT | ERR_ABORT;
3886 goto out;
3887 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003888 } else if (!strcmp(args[1], "show-node")) {
3889
3890 if (*args[2]) {
3891 int i;
3892 char c;
3893
3894 for (i=0; args[2][i]; i++) {
3895 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003896 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3897 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003898 break;
3899 }
3900
3901 if (!i || args[2][i]) {
3902 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3903 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3904 file, linenum, args[0], args[1]);
3905 err_code |= ERR_ALERT | ERR_FATAL;
3906 goto out;
3907 }
3908 }
3909
3910 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3911 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3912 err_code |= ERR_ALERT | ERR_ABORT;
3913 goto out;
3914 }
3915 } else if (!strcmp(args[1], "show-desc")) {
3916 char *desc = NULL;
3917
3918 if (*args[2]) {
3919 int i, len=0;
3920 char *d;
3921
Willy Tarreau348acfe2014-04-14 15:00:39 +02003922 for (i = 2; *args[i]; i++)
3923 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003924
3925 desc = d = (char *)calloc(1, len);
3926
Willy Tarreau348acfe2014-04-14 15:00:39 +02003927 d += snprintf(d, desc + len - d, "%s", args[2]);
3928 for (i = 3; *args[i]; i++)
3929 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003930 }
3931
3932 if (!*args[2] && !global.desc)
3933 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3934 file, linenum, args[1]);
3935 else {
3936 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3937 free(desc);
3938 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3939 err_code |= ERR_ALERT | ERR_ABORT;
3940 goto out;
3941 }
3942 free(desc);
3943 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003944 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003945stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003946 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 +01003947 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950 }
3951 }
3952 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003953 int optnum;
3954
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003955 if (*(args[1]) == '\0') {
3956 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3957 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003958 err_code |= ERR_ALERT | ERR_FATAL;
3959 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003960 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003961
3962 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3963 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003964 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3965 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3966 file, linenum, cfg_opts[optnum].name);
3967 err_code |= ERR_ALERT | ERR_FATAL;
3968 goto out;
3969 }
Willy Tarreau93893792009-07-23 13:19:11 +02003970 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3971 err_code |= ERR_WARN;
3972 goto out;
3973 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003974
Willy Tarreau3842f002009-06-14 11:39:52 +02003975 curproxy->no_options &= ~cfg_opts[optnum].val;
3976 curproxy->options &= ~cfg_opts[optnum].val;
3977
3978 switch (kwm) {
3979 case KWM_STD:
3980 curproxy->options |= cfg_opts[optnum].val;
3981 break;
3982 case KWM_NO:
3983 curproxy->no_options |= cfg_opts[optnum].val;
3984 break;
3985 case KWM_DEF: /* already cleared */
3986 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003987 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003988
Willy Tarreau93893792009-07-23 13:19:11 +02003989 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003990 }
3991 }
3992
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003993 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3994 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003995 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3996 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3997 file, linenum, cfg_opts2[optnum].name);
3998 err_code |= ERR_ALERT | ERR_FATAL;
3999 goto out;
4000 }
Willy Tarreau93893792009-07-23 13:19:11 +02004001 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4002 err_code |= ERR_WARN;
4003 goto out;
4004 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004005
Willy Tarreau3842f002009-06-14 11:39:52 +02004006 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4007 curproxy->options2 &= ~cfg_opts2[optnum].val;
4008
4009 switch (kwm) {
4010 case KWM_STD:
4011 curproxy->options2 |= cfg_opts2[optnum].val;
4012 break;
4013 case KWM_NO:
4014 curproxy->no_options2 |= cfg_opts2[optnum].val;
4015 break;
4016 case KWM_DEF: /* already cleared */
4017 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004018 }
Willy Tarreau93893792009-07-23 13:19:11 +02004019 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004020 }
4021 }
4022
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004023 /* HTTP options override each other. They can be cancelled using
4024 * "no option xxx" which only switches to default mode if the mode
4025 * was this one (useful for cancelling options set in defaults
4026 * sections).
4027 */
4028 if (strcmp(args[1], "httpclose") == 0) {
4029 if (kwm == KWM_STD) {
4030 curproxy->options &= ~PR_O_HTTP_MODE;
4031 curproxy->options |= PR_O_HTTP_PCL;
4032 goto out;
4033 }
4034 else if (kwm == KWM_NO) {
4035 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4036 curproxy->options &= ~PR_O_HTTP_MODE;
4037 goto out;
4038 }
4039 }
4040 else if (strcmp(args[1], "forceclose") == 0) {
4041 if (kwm == KWM_STD) {
4042 curproxy->options &= ~PR_O_HTTP_MODE;
4043 curproxy->options |= PR_O_HTTP_FCL;
4044 goto out;
4045 }
4046 else if (kwm == KWM_NO) {
4047 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4048 curproxy->options &= ~PR_O_HTTP_MODE;
4049 goto out;
4050 }
4051 }
4052 else if (strcmp(args[1], "http-server-close") == 0) {
4053 if (kwm == KWM_STD) {
4054 curproxy->options &= ~PR_O_HTTP_MODE;
4055 curproxy->options |= PR_O_HTTP_SCL;
4056 goto out;
4057 }
4058 else if (kwm == KWM_NO) {
4059 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4060 curproxy->options &= ~PR_O_HTTP_MODE;
4061 goto out;
4062 }
4063 }
4064 else if (strcmp(args[1], "http-keep-alive") == 0) {
4065 if (kwm == KWM_STD) {
4066 curproxy->options &= ~PR_O_HTTP_MODE;
4067 curproxy->options |= PR_O_HTTP_KAL;
4068 goto out;
4069 }
4070 else if (kwm == KWM_NO) {
4071 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4072 curproxy->options &= ~PR_O_HTTP_MODE;
4073 goto out;
4074 }
4075 }
4076 else if (strcmp(args[1], "http-tunnel") == 0) {
4077 if (kwm == KWM_STD) {
4078 curproxy->options &= ~PR_O_HTTP_MODE;
4079 curproxy->options |= PR_O_HTTP_TUN;
4080 goto out;
4081 }
4082 else if (kwm == KWM_NO) {
4083 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4084 curproxy->options &= ~PR_O_HTTP_MODE;
4085 goto out;
4086 }
4087 }
4088
Willy Tarreau3842f002009-06-14 11:39:52 +02004089 if (kwm != KWM_STD) {
4090 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004091 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004092 err_code |= ERR_ALERT | ERR_FATAL;
4093 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004094 }
4095
Emeric Brun3a058f32009-06-30 18:26:00 +02004096 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004097 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004098 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004099 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004100 if (*(args[2]) != '\0') {
4101 if (!strcmp(args[2], "clf")) {
4102 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004103 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004104 } else {
4105 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02004106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004108 }
4109 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004110 if (curproxy->conf.logformat_string != default_http_log_format &&
4111 curproxy->conf.logformat_string != default_tcp_log_format &&
4112 curproxy->conf.logformat_string != clf_http_log_format)
4113 free(curproxy->conf.logformat_string);
4114 curproxy->conf.logformat_string = logformat;
4115
4116 free(curproxy->conf.lfs_file);
4117 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4118 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004119 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004120 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004121 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004122 if (curproxy->conf.logformat_string != default_http_log_format &&
4123 curproxy->conf.logformat_string != default_tcp_log_format &&
4124 curproxy->conf.logformat_string != clf_http_log_format)
4125 free(curproxy->conf.logformat_string);
4126 curproxy->conf.logformat_string = default_tcp_log_format;
4127
4128 free(curproxy->conf.lfs_file);
4129 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4130 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004131 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004132 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004133 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004134 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004135 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004136
4137 if (curproxy->cap & PR_CAP_FE)
4138 curproxy->options |= PR_O_TCP_CLI_KA;
4139 if (curproxy->cap & PR_CAP_BE)
4140 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004141 }
4142 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004143 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004144 err_code |= ERR_WARN;
4145
Willy Tarreaubaaee002006-06-26 02:48:02 +02004146 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004147 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004148 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004149 curproxy->options2 &= ~PR_O2_CHK_ANY;
4150 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004151 if (!*args[2]) { /* no argument */
4152 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4153 curproxy->check_len = strlen(DEF_CHECK_REQ);
4154 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004155 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004156 curproxy->check_req = (char *)malloc(reqlen);
4157 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004158 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004159 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004160 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004161 if (*args[4])
4162 reqlen += strlen(args[4]);
4163 else
4164 reqlen += strlen("HTTP/1.0");
4165
4166 curproxy->check_req = (char *)malloc(reqlen);
4167 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004168 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004169 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004170 }
4171 else if (!strcmp(args[1], "ssl-hello-chk")) {
4172 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004173 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004174 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004175
Willy Tarreaua534fea2008-08-03 12:19:50 +02004176 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004177 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004178 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004179 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004180 }
Willy Tarreau23677902007-05-08 23:50:35 +02004181 else if (!strcmp(args[1], "smtpchk")) {
4182 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004183 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004184 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004185 curproxy->options2 &= ~PR_O2_CHK_ANY;
4186 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004187
4188 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4189 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4190 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4191 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4192 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4193 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4194 curproxy->check_req = (char *)malloc(reqlen);
4195 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4196 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4197 } else {
4198 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4199 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4200 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4201 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4202 }
4203 }
4204 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004205 else if (!strcmp(args[1], "pgsql-check")) {
4206 /* use PostgreSQL request to check servers' health */
4207 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4208 err_code |= ERR_WARN;
4209
4210 free(curproxy->check_req);
4211 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004212 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004213 curproxy->options2 |= PR_O2_PGSQL_CHK;
4214
4215 if (*(args[2])) {
4216 int cur_arg = 2;
4217
4218 while (*(args[cur_arg])) {
4219 if (strcmp(args[cur_arg], "user") == 0) {
4220 char * packet;
4221 uint32_t packet_len;
4222 uint32_t pv;
4223
4224 /* suboption header - needs additional argument for it */
4225 if (*(args[cur_arg+1]) == 0) {
4226 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4227 file, linenum, args[0], args[1], args[cur_arg]);
4228 err_code |= ERR_ALERT | ERR_FATAL;
4229 goto out;
4230 }
4231
4232 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4233 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4234 pv = htonl(0x30000); /* protocol version 3.0 */
4235
4236 packet = (char*) calloc(1, packet_len);
4237
4238 memcpy(packet + 4, &pv, 4);
4239
4240 /* copy "user" */
4241 memcpy(packet + 8, "user", 4);
4242
4243 /* copy username */
4244 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4245
4246 free(curproxy->check_req);
4247 curproxy->check_req = packet;
4248 curproxy->check_len = packet_len;
4249
4250 packet_len = htonl(packet_len);
4251 memcpy(packet, &packet_len, 4);
4252 cur_arg += 2;
4253 } else {
4254 /* unknown suboption - catchall */
4255 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4256 file, linenum, args[0], args[1]);
4257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
4259 }
4260 } /* end while loop */
4261 }
4262 }
4263
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004264 else if (!strcmp(args[1], "redis-check")) {
4265 /* use REDIS PING request to check servers' health */
4266 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4267 err_code |= ERR_WARN;
4268
4269 free(curproxy->check_req);
4270 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004271 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004272 curproxy->options2 |= PR_O2_REDIS_CHK;
4273
4274 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4275 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4276 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4277 }
4278
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004279 else if (!strcmp(args[1], "mysql-check")) {
4280 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004281 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4282 err_code |= ERR_WARN;
4283
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004284 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004285 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004286 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004287 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004288
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004289 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004290 * const char mysql40_client_auth_pkt[] = {
4291 * "\x0e\x00\x00" // packet length
4292 * "\x01" // packet number
4293 * "\x00\x00" // client capabilities
4294 * "\x00\x00\x01" // max packet
4295 * "haproxy\x00" // username (null terminated string)
4296 * "\x00" // filler (always 0x00)
4297 * "\x01\x00\x00" // packet length
4298 * "\x00" // packet number
4299 * "\x01" // COM_QUIT command
4300 * };
4301 */
4302
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004303 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4304 * const char mysql41_client_auth_pkt[] = {
4305 * "\x0e\x00\x00\" // packet length
4306 * "\x01" // packet number
4307 * "\x00\x00\x00\x00" // client capabilities
4308 * "\x00\x00\x00\x01" // max packet
4309 * "\x21" // character set (UTF-8)
4310 * char[23] // All zeroes
4311 * "haproxy\x00" // username (null terminated string)
4312 * "\x00" // filler (always 0x00)
4313 * "\x01\x00\x00" // packet length
4314 * "\x00" // packet number
4315 * "\x01" // COM_QUIT command
4316 * };
4317 */
4318
4319
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004320 if (*(args[2])) {
4321 int cur_arg = 2;
4322
4323 while (*(args[cur_arg])) {
4324 if (strcmp(args[cur_arg], "user") == 0) {
4325 char *mysqluser;
4326 int packetlen, reqlen, userlen;
4327
4328 /* suboption header - needs additional argument for it */
4329 if (*(args[cur_arg+1]) == 0) {
4330 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4331 file, linenum, args[0], args[1], args[cur_arg]);
4332 err_code |= ERR_ALERT | ERR_FATAL;
4333 goto out;
4334 }
4335 mysqluser = args[cur_arg + 1];
4336 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004337
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004338 if (*(args[cur_arg+2])) {
4339 if (!strcmp(args[cur_arg+2], "post-41")) {
4340 packetlen = userlen + 7 + 27;
4341 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004342
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004343 free(curproxy->check_req);
4344 curproxy->check_req = (char *)calloc(1, reqlen);
4345 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004346
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004347 snprintf(curproxy->check_req, 4, "%c%c%c",
4348 ((unsigned char) packetlen & 0xff),
4349 ((unsigned char) (packetlen >> 8) & 0xff),
4350 ((unsigned char) (packetlen >> 16) & 0xff));
4351
4352 curproxy->check_req[3] = 1;
4353 curproxy->check_req[5] = 130;
4354 curproxy->check_req[11] = 1;
4355 curproxy->check_req[12] = 33;
4356 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4357 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4358 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4359 cur_arg += 3;
4360 } else {
4361 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4362 err_code |= ERR_ALERT | ERR_FATAL;
4363 goto out;
4364 }
4365 } else {
4366 packetlen = userlen + 7;
4367 reqlen = packetlen + 9;
4368
4369 free(curproxy->check_req);
4370 curproxy->check_req = (char *)calloc(1, reqlen);
4371 curproxy->check_len = reqlen;
4372
4373 snprintf(curproxy->check_req, 4, "%c%c%c",
4374 ((unsigned char) packetlen & 0xff),
4375 ((unsigned char) (packetlen >> 8) & 0xff),
4376 ((unsigned char) (packetlen >> 16) & 0xff));
4377
4378 curproxy->check_req[3] = 1;
4379 curproxy->check_req[5] = 128;
4380 curproxy->check_req[8] = 1;
4381 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4382 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4383 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4384 cur_arg += 2;
4385 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004386 } else {
4387 /* unknown suboption - catchall */
4388 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4389 file, linenum, args[0], args[1]);
4390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
4392 }
4393 } /* end while loop */
4394 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004395 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004396 else if (!strcmp(args[1], "ldap-check")) {
4397 /* use LDAP request to check servers' health */
4398 free(curproxy->check_req);
4399 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004400 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004401 curproxy->options2 |= PR_O2_LDAP_CHK;
4402
4403 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4404 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4405 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4406 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004407 else if (!strcmp(args[1], "tcp-check")) {
4408 /* use raw TCPCHK send/expect to check servers' health */
4409 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4410 err_code |= ERR_WARN;
4411
4412 free(curproxy->check_req);
4413 curproxy->check_req = NULL;
4414 curproxy->options2 &= ~PR_O2_CHK_ANY;
4415 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4416 }
Simon Horman98637e52014-06-20 12:30:16 +09004417 else if (!strcmp(args[1], "external-check")) {
4418 /* excute an external command to check servers' health */
4419 free(curproxy->check_req);
4420 curproxy->check_req = NULL;
4421 curproxy->options2 &= ~PR_O2_CHK_ANY;
4422 curproxy->options2 |= PR_O2_EXT_CHK;
4423 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004424 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004425 int cur_arg;
4426
4427 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4428 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004429 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004430
Willy Tarreau87cf5142011-08-19 22:57:24 +02004431 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004432
4433 free(curproxy->fwdfor_hdr_name);
4434 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4435 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4436
4437 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4438 cur_arg = 2;
4439 while (*(args[cur_arg])) {
4440 if (!strcmp(args[cur_arg], "except")) {
4441 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004442 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004443 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4444 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004445 err_code |= ERR_ALERT | ERR_FATAL;
4446 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004447 }
4448 /* flush useless bits */
4449 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004450 cur_arg += 2;
4451 } else if (!strcmp(args[cur_arg], "header")) {
4452 /* suboption header - needs additional argument for it */
4453 if (*(args[cur_arg+1]) == 0) {
4454 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4455 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004456 err_code |= ERR_ALERT | ERR_FATAL;
4457 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004458 }
4459 free(curproxy->fwdfor_hdr_name);
4460 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4461 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4462 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004463 } else if (!strcmp(args[cur_arg], "if-none")) {
4464 curproxy->options &= ~PR_O_FF_ALWAYS;
4465 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004466 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004467 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004468 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004469 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004470 err_code |= ERR_ALERT | ERR_FATAL;
4471 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004472 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004473 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004474 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004475 else if (!strcmp(args[1], "originalto")) {
4476 int cur_arg;
4477
4478 /* insert x-original-to field, but not for the IP address listed as an except.
4479 * set default options (ie: bitfield, header name, etc)
4480 */
4481
4482 curproxy->options |= PR_O_ORGTO;
4483
4484 free(curproxy->orgto_hdr_name);
4485 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4486 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4487
Willy Tarreau87cf5142011-08-19 22:57:24 +02004488 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004489 cur_arg = 2;
4490 while (*(args[cur_arg])) {
4491 if (!strcmp(args[cur_arg], "except")) {
4492 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004493 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 +02004494 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4495 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004496 err_code |= ERR_ALERT | ERR_FATAL;
4497 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004498 }
4499 /* flush useless bits */
4500 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4501 cur_arg += 2;
4502 } else if (!strcmp(args[cur_arg], "header")) {
4503 /* suboption header - needs additional argument for it */
4504 if (*(args[cur_arg+1]) == 0) {
4505 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4506 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004507 err_code |= ERR_ALERT | ERR_FATAL;
4508 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004509 }
4510 free(curproxy->orgto_hdr_name);
4511 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4512 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4513 cur_arg += 2;
4514 } else {
4515 /* unknown suboption - catchall */
4516 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4517 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004518 err_code |= ERR_ALERT | ERR_FATAL;
4519 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004520 }
4521 } /* end while loop */
4522 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004523 else {
4524 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004525 err_code |= ERR_ALERT | ERR_FATAL;
4526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004527 }
Willy Tarreau93893792009-07-23 13:19:11 +02004528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004529 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004530 else if (!strcmp(args[0], "default_backend")) {
4531 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004532 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004533
4534 if (*(args[1]) == 0) {
4535 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004536 err_code |= ERR_ALERT | ERR_FATAL;
4537 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004538 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004539 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004540 curproxy->defbe.name = strdup(args[1]);
4541 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004542 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004543 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004544 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004545
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004546 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4547 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 +01004548 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004549 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004550 /* enable reconnections to dispatch */
4551 curproxy->options |= PR_O_REDISP;
4552 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004553 else if (!strcmp(args[0], "http-check")) {
4554 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004555 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004556
4557 if (strcmp(args[1], "disable-on-404") == 0) {
4558 /* enable a graceful server shutdown on an HTTP 404 response */
4559 curproxy->options |= PR_O_DISABLE404;
4560 }
Willy Tarreauef781042010-01-27 11:53:01 +01004561 else if (strcmp(args[1], "send-state") == 0) {
4562 /* enable emission of the apparent state of a server in HTTP checks */
4563 curproxy->options2 |= PR_O2_CHK_SNDST;
4564 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004565 else if (strcmp(args[1], "expect") == 0) {
4566 const char *ptr_arg;
4567 int cur_arg;
4568
4569 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4570 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4571 err_code |= ERR_ALERT | ERR_FATAL;
4572 goto out;
4573 }
4574
4575 cur_arg = 2;
4576 /* consider exclamation marks, sole or at the beginning of a word */
4577 while (*(ptr_arg = args[cur_arg])) {
4578 while (*ptr_arg == '!') {
4579 curproxy->options2 ^= PR_O2_EXP_INV;
4580 ptr_arg++;
4581 }
4582 if (*ptr_arg)
4583 break;
4584 cur_arg++;
4585 }
4586 /* now ptr_arg points to the beginning of a word past any possible
4587 * exclamation mark, and cur_arg is the argument which holds this word.
4588 */
4589 if (strcmp(ptr_arg, "status") == 0) {
4590 if (!*(args[cur_arg + 1])) {
4591 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4592 file, linenum, args[0], args[1], ptr_arg);
4593 err_code |= ERR_ALERT | ERR_FATAL;
4594 goto out;
4595 }
4596 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004597 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004598 curproxy->expect_str = strdup(args[cur_arg + 1]);
4599 }
4600 else if (strcmp(ptr_arg, "string") == 0) {
4601 if (!*(args[cur_arg + 1])) {
4602 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4603 file, linenum, args[0], args[1], ptr_arg);
4604 err_code |= ERR_ALERT | ERR_FATAL;
4605 goto out;
4606 }
4607 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004608 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004609 curproxy->expect_str = strdup(args[cur_arg + 1]);
4610 }
4611 else if (strcmp(ptr_arg, "rstatus") == 0) {
4612 if (!*(args[cur_arg + 1])) {
4613 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4614 file, linenum, args[0], args[1], ptr_arg);
4615 err_code |= ERR_ALERT | ERR_FATAL;
4616 goto out;
4617 }
4618 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004619 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004620 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004621 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004622 free(curproxy->expect_regex);
4623 curproxy->expect_regex = NULL;
4624 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004625 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004626 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4627 error = NULL;
4628 if (!regex_comp(args[cur_arg + 1], curproxy->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);
Willy Tarreaubd741542010-03-16 18:46:54 +01004632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
4634 }
4635 }
4636 else if (strcmp(ptr_arg, "rstring") == 0) {
4637 if (!*(args[cur_arg + 1])) {
4638 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4639 file, linenum, args[0], args[1], ptr_arg);
4640 err_code |= ERR_ALERT | ERR_FATAL;
4641 goto out;
4642 }
4643 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004644 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004645 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004646 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004647 free(curproxy->expect_regex);
4648 curproxy->expect_regex = NULL;
4649 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004650 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004651 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4652 error = NULL;
4653 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4654 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4655 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4656 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004657 err_code |= ERR_ALERT | ERR_FATAL;
4658 goto out;
4659 }
4660 }
4661 else {
4662 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4663 file, linenum, args[0], args[1], ptr_arg);
4664 err_code |= ERR_ALERT | ERR_FATAL;
4665 goto out;
4666 }
4667 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004668 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004669 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 +02004670 err_code |= ERR_ALERT | ERR_FATAL;
4671 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004672 }
4673 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004674 else if (!strcmp(args[0], "tcp-check")) {
4675 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4676 err_code |= ERR_WARN;
4677
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004678 if (strcmp(args[1], "connect") == 0) {
4679 const char *ptr_arg;
4680 int cur_arg;
4681 struct tcpcheck_rule *tcpcheck;
4682 struct list *l;
4683
4684 /* check if first rule is also a 'connect' action */
4685 l = (struct list *)&curproxy->tcpcheck_rules;
4686 if (l->p != l->n) {
4687 tcpcheck = (struct tcpcheck_rule *)l->n;
4688 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4689 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4690 file, linenum);
4691 err_code |= ERR_ALERT | ERR_FATAL;
4692 goto out;
4693 }
4694 }
4695
4696 cur_arg = 2;
4697 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4698 tcpcheck->action = TCPCHK_ACT_CONNECT;
4699
4700 /* parsing each parameters to fill up the rule */
4701 while (*(ptr_arg = args[cur_arg])) {
4702 /* tcp port */
4703 if (strcmp(args[cur_arg], "port") == 0) {
4704 if ( (atol(args[cur_arg + 1]) > 65535) ||
4705 (atol(args[cur_arg + 1]) < 1) ){
4706 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4707 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4708 err_code |= ERR_ALERT | ERR_FATAL;
4709 goto out;
4710 }
4711 tcpcheck->port = atol(args[cur_arg + 1]);
4712 cur_arg += 2;
4713 }
4714 /* send proxy protocol */
4715 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4716 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4717 cur_arg++;
4718 }
4719#ifdef USE_OPENSSL
4720 else if (strcmp(args[cur_arg], "ssl") == 0) {
4721 curproxy->options |= PR_O_TCPCHK_SSL;
4722 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4723 cur_arg++;
4724 }
4725#endif /* USE_OPENSSL */
4726 else {
4727#ifdef USE_OPENSSL
4728 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4729#else /* USE_OPENSSL */
4730 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4731#endif /* USE_OPENSSL */
4732 file, linenum, args[0], args[1], args[cur_arg]);
4733 err_code |= ERR_ALERT | ERR_FATAL;
4734 goto out;
4735 }
4736
4737 }
4738
4739 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4740 }
4741 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004742 if (! *(args[2]) ) {
4743 /* SEND string expected */
4744 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4745 file, linenum, args[0], args[1], args[2]);
4746 err_code |= ERR_ALERT | ERR_FATAL;
4747 goto out;
4748 } else {
4749 struct tcpcheck_rule *tcpcheck;
4750
4751 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4752
4753 tcpcheck->action = TCPCHK_ACT_SEND;
4754 tcpcheck->string_len = strlen(args[2]);
4755 tcpcheck->string = strdup(args[2]);
4756 tcpcheck->expect_regex = NULL;
4757
4758 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4759 }
4760 }
4761 else if (strcmp(args[1], "send-binary") == 0) {
4762 if (! *(args[2]) ) {
4763 /* SEND binary string expected */
4764 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4765 file, linenum, args[0], args[1], args[2]);
4766 err_code |= ERR_ALERT | ERR_FATAL;
4767 goto out;
4768 } else {
4769 struct tcpcheck_rule *tcpcheck;
4770 char *err = NULL;
4771
4772 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4773
4774 tcpcheck->action = TCPCHK_ACT_SEND;
4775 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4776 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4777 file, linenum, args[0], args[1], args[2], err);
4778 err_code |= ERR_ALERT | ERR_FATAL;
4779 goto out;
4780 }
4781 tcpcheck->expect_regex = NULL;
4782
4783 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4784 }
4785 }
4786 else if (strcmp(args[1], "expect") == 0) {
4787 const char *ptr_arg;
4788 int cur_arg;
4789 int inverse = 0;
4790
4791 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4792 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4793 err_code |= ERR_ALERT | ERR_FATAL;
4794 goto out;
4795 }
4796
4797 cur_arg = 2;
4798 /* consider exclamation marks, sole or at the beginning of a word */
4799 while (*(ptr_arg = args[cur_arg])) {
4800 while (*ptr_arg == '!') {
4801 inverse = !inverse;
4802 ptr_arg++;
4803 }
4804 if (*ptr_arg)
4805 break;
4806 cur_arg++;
4807 }
4808 /* now ptr_arg points to the beginning of a word past any possible
4809 * exclamation mark, and cur_arg is the argument which holds this word.
4810 */
4811 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004812 struct tcpcheck_rule *tcpcheck;
4813 char *err = NULL;
4814
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004815 if (!*(args[cur_arg + 1])) {
4816 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4817 file, linenum, args[0], args[1], ptr_arg);
4818 err_code |= ERR_ALERT | ERR_FATAL;
4819 goto out;
4820 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004821
4822 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4823
4824 tcpcheck->action = TCPCHK_ACT_EXPECT;
4825 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4826 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4827 file, linenum, args[0], args[1], args[2], err);
4828 err_code |= ERR_ALERT | ERR_FATAL;
4829 goto out;
4830 }
4831 tcpcheck->expect_regex = NULL;
4832 tcpcheck->inverse = inverse;
4833
4834 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4835 }
4836 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004837 struct tcpcheck_rule *tcpcheck;
4838
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004839 if (!*(args[cur_arg + 1])) {
4840 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4841 file, linenum, args[0], args[1], ptr_arg);
4842 err_code |= ERR_ALERT | ERR_FATAL;
4843 goto out;
4844 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004845
4846 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4847
4848 tcpcheck->action = TCPCHK_ACT_EXPECT;
4849 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4850 tcpcheck->string = strdup(args[cur_arg + 1]);
4851 tcpcheck->expect_regex = NULL;
4852 tcpcheck->inverse = inverse;
4853
4854 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4855 }
4856 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004857 struct tcpcheck_rule *tcpcheck;
4858
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004859 if (!*(args[cur_arg + 1])) {
4860 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4861 file, linenum, args[0], args[1], ptr_arg);
4862 err_code |= ERR_ALERT | ERR_FATAL;
4863 goto out;
4864 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004865
4866 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4867
4868 tcpcheck->action = TCPCHK_ACT_EXPECT;
4869 tcpcheck->string_len = 0;
4870 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004871 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4872 error = NULL;
4873 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4874 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4875 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4876 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004877 err_code |= ERR_ALERT | ERR_FATAL;
4878 goto out;
4879 }
4880 tcpcheck->inverse = inverse;
4881
4882 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4883 }
4884 else {
4885 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4886 file, linenum, args[0], args[1], ptr_arg);
4887 err_code |= ERR_ALERT | ERR_FATAL;
4888 goto out;
4889 }
4890 }
4891 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004892 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004893 err_code |= ERR_ALERT | ERR_FATAL;
4894 goto out;
4895 }
4896 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004897 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004898 if (curproxy == &defproxy) {
4899 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004902 }
4903
Willy Tarreaub80c2302007-11-30 20:51:32 +01004904 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004905 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004906
4907 if (strcmp(args[1], "fail") == 0) {
4908 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004909 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004910 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4911 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004912 err_code |= ERR_ALERT | ERR_FATAL;
4913 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004914 }
4915
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004916 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4917 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4918 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004919 err_code |= ERR_ALERT | ERR_FATAL;
4920 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004921 }
4922 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4923 }
4924 else {
4925 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004926 err_code |= ERR_ALERT | ERR_FATAL;
4927 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004928 }
4929 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004930#ifdef TPROXY
4931 else if (!strcmp(args[0], "transparent")) {
4932 /* enable transparent proxy connections */
4933 curproxy->options |= PR_O_TRANSP;
4934 }
4935#endif
4936 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004937 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004938 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004939
Willy Tarreaubaaee002006-06-26 02:48:02 +02004940 if (*(args[1]) == 0) {
4941 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004942 err_code |= ERR_ALERT | ERR_FATAL;
4943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004944 }
4945 curproxy->maxconn = atol(args[1]);
4946 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004947 else if (!strcmp(args[0], "backlog")) { /* backlog */
4948 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004949 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004950
4951 if (*(args[1]) == 0) {
4952 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004953 err_code |= ERR_ALERT | ERR_FATAL;
4954 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004955 }
4956 curproxy->backlog = atol(args[1]);
4957 }
Willy Tarreau86034312006-12-29 00:10:33 +01004958 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004959 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004960 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004961
Willy Tarreau86034312006-12-29 00:10:33 +01004962 if (*(args[1]) == 0) {
4963 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004964 err_code |= ERR_ALERT | ERR_FATAL;
4965 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004966 }
4967 curproxy->fullconn = atol(args[1]);
4968 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004969 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4970 if (*(args[1]) == 0) {
4971 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004972 err_code |= ERR_ALERT | ERR_FATAL;
4973 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004974 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004975 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4976 if (err) {
4977 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4978 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004979 err_code |= ERR_ALERT | ERR_FATAL;
4980 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004981 }
4982 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004983 }
4984 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004985 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004986 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004987 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004988
Willy Tarreaubaaee002006-06-26 02:48:02 +02004989 if (curproxy == &defproxy) {
4990 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004991 err_code |= ERR_ALERT | ERR_FATAL;
4992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004993 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004994 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004995 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004996
Willy Tarreau902636f2013-03-10 19:44:48 +01004997 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004998 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004999 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005000 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005001 goto out;
5002 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005003
5004 proto = protocol_by_family(sk->ss_family);
5005 if (!proto || !proto->connect) {
5006 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5007 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005008 err_code |= ERR_ALERT | ERR_FATAL;
5009 goto out;
5010 }
5011
5012 if (port1 != port2) {
5013 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5014 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005015 err_code |= ERR_ALERT | ERR_FATAL;
5016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005017 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005018
5019 if (!port1) {
5020 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5021 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005022 err_code |= ERR_ALERT | ERR_FATAL;
5023 goto out;
5024 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005025
Willy Tarreaud5191e72010-02-09 20:50:45 +01005026 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005027 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005028 }
5029 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005030 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005031 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005032
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005033 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5034 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005035 err_code |= ERR_ALERT | ERR_FATAL;
5036 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005037 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005038 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005039 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005040 /**
5041 * The syntax for hash-type config element is
5042 * hash-type {map-based|consistent} [[<algo>] avalanche]
5043 *
5044 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5045 */
5046 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005047
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005048 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5049 err_code |= ERR_WARN;
5050
5051 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005052 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5053 }
5054 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005055 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5056 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005057 else if (strcmp(args[1], "avalanche") == 0) {
5058 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]);
5059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005061 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005062 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005063 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005064 err_code |= ERR_ALERT | ERR_FATAL;
5065 goto out;
5066 }
Bhaskar98634f02013-10-29 23:30:51 -04005067
5068 /* set the hash function to use */
5069 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005070 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005071 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005072
5073 /* if consistent with no argument, then avalanche modifier is also applied */
5074 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5075 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005076 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005077 /* set the hash function */
5078 if (!strcmp(args[2], "sdbm")) {
5079 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5080 }
5081 else if (!strcmp(args[2], "djb2")) {
5082 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005083 }
5084 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005085 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005086 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005087 else if (!strcmp(args[2], "crc32")) {
5088 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5089 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005090 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005091 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 -05005092 err_code |= ERR_ALERT | ERR_FATAL;
5093 goto out;
5094 }
5095
5096 /* set the hash modifier */
5097 if (!strcmp(args[3], "avalanche")) {
5098 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5099 }
5100 else if (*args[3]) {
5101 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5102 err_code |= ERR_ALERT | ERR_FATAL;
5103 goto out;
5104 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005105 }
William Lallemanda73203e2012-03-12 12:48:57 +01005106 }
William Lallemanda73203e2012-03-12 12:48:57 +01005107 else if (strcmp(args[0], "unique-id-format") == 0) {
5108 if (!*(args[1])) {
5109 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5110 err_code |= ERR_ALERT | ERR_FATAL;
5111 goto out;
5112 }
William Lallemand3203ff42012-11-11 17:30:56 +01005113 if (*(args[2])) {
5114 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
5117 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005118 free(curproxy->conf.uniqueid_format_string);
5119 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005120
Willy Tarreau62a61232013-04-12 18:13:46 +02005121 free(curproxy->conf.uif_file);
5122 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5123 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005124 }
William Lallemanda73203e2012-03-12 12:48:57 +01005125
5126 else if (strcmp(args[0], "unique-id-header") == 0) {
5127 if (!*(args[1])) {
5128 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5129 err_code |= ERR_ALERT | ERR_FATAL;
5130 goto out;
5131 }
5132 free(curproxy->header_unique_id);
5133 curproxy->header_unique_id = strdup(args[1]);
5134 }
5135
William Lallemand723b73a2012-02-08 16:37:49 +01005136 else if (strcmp(args[0], "log-format") == 0) {
5137 if (!*(args[1])) {
5138 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5139 err_code |= ERR_ALERT | ERR_FATAL;
5140 goto out;
5141 }
William Lallemand3203ff42012-11-11 17:30:56 +01005142 if (*(args[2])) {
5143 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5144 err_code |= ERR_ALERT | ERR_FATAL;
5145 goto out;
5146 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005147
Willy Tarreau62a61232013-04-12 18:13:46 +02005148 if (curproxy->conf.logformat_string != default_http_log_format &&
5149 curproxy->conf.logformat_string != default_tcp_log_format &&
5150 curproxy->conf.logformat_string != clf_http_log_format)
5151 free(curproxy->conf.logformat_string);
5152 curproxy->conf.logformat_string = strdup(args[1]);
5153
5154 free(curproxy->conf.lfs_file);
5155 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5156 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005157
5158 /* get a chance to improve log-format error reporting by
5159 * reporting the correct line-number when possible.
5160 */
5161 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5162 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5163 file, linenum, curproxy->id);
5164 err_code |= ERR_WARN;
5165 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005166 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005167 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5168 if (*(args[1]) == 0) {
5169 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5170 err_code |= ERR_ALERT | ERR_FATAL;
5171 goto out;
5172 }
5173 free(curproxy->log_tag);
5174 curproxy->log_tag = strdup(args[1]);
5175 }
William Lallemand0f99e342011-10-12 17:50:54 +02005176 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5177 /* delete previous herited or defined syslog servers */
5178 struct logsrv *back;
5179
5180 if (*(args[1]) != 0) {
5181 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5182 err_code |= ERR_ALERT | ERR_FATAL;
5183 goto out;
5184 }
5185
William Lallemand723b73a2012-02-08 16:37:49 +01005186 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5187 LIST_DEL(&tmplogsrv->list);
5188 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005189 }
5190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005191 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005192 struct logsrv *logsrv;
5193
Willy Tarreaubaaee002006-06-26 02:48:02 +02005194 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005195 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005196 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005197 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005198 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005199 LIST_INIT(&node->list);
5200 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5201 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005202 }
5203 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005204 struct sockaddr_storage *sk;
5205 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005206 int arg = 0;
5207 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005208
5209 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210
Willy Tarreau18324f52014-06-27 18:10:07 +02005211 /* just after the address, a length may be specified */
5212 if (strcmp(args[arg+2], "len") == 0) {
5213 len = atoi(args[arg+3]);
5214 if (len < 80 || len > 65535) {
5215 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5216 file, linenum, args[arg+3]);
5217 err_code |= ERR_ALERT | ERR_FATAL;
5218 goto out;
5219 }
5220 logsrv->maxlen = len;
5221
5222 /* skip these two args */
5223 arg += 2;
5224 }
5225 else
5226 logsrv->maxlen = MAX_SYSLOG_LEN;
5227
5228 if (logsrv->maxlen > global.max_syslog_len) {
5229 global.max_syslog_len = logsrv->maxlen;
5230 logline = realloc(logline, global.max_syslog_len + 1);
5231 }
5232
5233 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005234 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005235 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005236 err_code |= ERR_ALERT | ERR_FATAL;
5237 goto out;
5238
Willy Tarreaubaaee002006-06-26 02:48:02 +02005239 }
5240
William Lallemand0f99e342011-10-12 17:50:54 +02005241 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005242 if (*(args[arg+3])) {
5243 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005244 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005245 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005246 err_code |= ERR_ALERT | ERR_FATAL;
5247 goto out;
5248
Willy Tarreaubaaee002006-06-26 02:48:02 +02005249 }
5250 }
5251
William Lallemand0f99e342011-10-12 17:50:54 +02005252 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005253 if (*(args[arg+4])) {
5254 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005255 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005256 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005257 err_code |= ERR_ALERT | ERR_FATAL;
5258 goto out;
5259
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005260 }
5261 }
5262
Willy Tarreau902636f2013-03-10 19:44:48 +01005263 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005264 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005265 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005266 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005267 goto out;
5268 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005269
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005270 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005271
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005272 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005273 if (port1 != port2) {
5274 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5275 file, linenum, args[0], args[1]);
5276 err_code |= ERR_ALERT | ERR_FATAL;
5277 goto out;
5278 }
5279
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005280 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005281 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005282 }
William Lallemand0f99e342011-10-12 17:50:54 +02005283
5284 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005285 }
5286 else {
5287 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5288 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005289 err_code |= ERR_ALERT | ERR_FATAL;
5290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291 }
5292 }
5293 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005294 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005295 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005296 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005297 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005298
Willy Tarreau977b8e42006-12-29 14:19:17 +01005299 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005300 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005301
Willy Tarreaubaaee002006-06-26 02:48:02 +02005302 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005303 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5304 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005305 err_code |= ERR_ALERT | ERR_FATAL;
5306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005307 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005308
5309 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005310 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5311 free(curproxy->conn_src.iface_name);
5312 curproxy->conn_src.iface_name = NULL;
5313 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005314
Willy Tarreau902636f2013-03-10 19:44:48 +01005315 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005316 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005317 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005318 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005319 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005320 goto out;
5321 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005322
5323 proto = protocol_by_family(sk->ss_family);
5324 if (!proto || !proto->connect) {
5325 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005326 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005327 err_code |= ERR_ALERT | ERR_FATAL;
5328 goto out;
5329 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005330
5331 if (port1 != port2) {
5332 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5333 file, linenum, args[0], args[1]);
5334 err_code |= ERR_ALERT | ERR_FATAL;
5335 goto out;
5336 }
5337
Willy Tarreauef9a3602012-12-08 22:29:20 +01005338 curproxy->conn_src.source_addr = *sk;
5339 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005340
5341 cur_arg = 2;
5342 while (*(args[cur_arg])) {
5343 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005344#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5345#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005346 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005347 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5348 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005349 err_code |= ERR_ALERT | ERR_FATAL;
5350 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005351 }
5352#endif
5353 if (!*args[cur_arg + 1]) {
5354 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5355 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005356 err_code |= ERR_ALERT | ERR_FATAL;
5357 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005358 }
5359
5360 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005361 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5362 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005363 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005364 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5365 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005366 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5367 char *name, *end;
5368
5369 name = args[cur_arg+1] + 7;
5370 while (isspace(*name))
5371 name++;
5372
5373 end = name;
5374 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5375 end++;
5376
Willy Tarreauef9a3602012-12-08 22:29:20 +01005377 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5378 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5379 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5380 curproxy->conn_src.bind_hdr_len = end - name;
5381 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5382 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5383 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005384
5385 /* now look for an occurrence number */
5386 while (isspace(*end))
5387 end++;
5388 if (*end == ',') {
5389 end++;
5390 name = end;
5391 if (*end == '-')
5392 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005393 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005394 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005395 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005396 }
5397
Willy Tarreauef9a3602012-12-08 22:29:20 +01005398 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005399 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5400 " occurrences values smaller than %d.\n",
5401 file, linenum, MAX_HDR_HISTORY);
5402 err_code |= ERR_ALERT | ERR_FATAL;
5403 goto out;
5404 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005405 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005406 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005407
Willy Tarreau902636f2013-03-10 19:44:48 +01005408 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005409 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005410 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005411 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005412 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005413 goto out;
5414 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005415
5416 proto = protocol_by_family(sk->ss_family);
5417 if (!proto || !proto->connect) {
5418 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5419 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005420 err_code |= ERR_ALERT | ERR_FATAL;
5421 goto out;
5422 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005423
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005424 if (port1 != port2) {
5425 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5426 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005427 err_code |= ERR_ALERT | ERR_FATAL;
5428 goto out;
5429 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005430 curproxy->conn_src.tproxy_addr = *sk;
5431 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005432 }
5433 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005434#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005435 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005436#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005437#else /* no TPROXY support */
5438 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005439 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005440 err_code |= ERR_ALERT | ERR_FATAL;
5441 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005442#endif
5443 cur_arg += 2;
5444 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005445 }
5446
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005447 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5448#ifdef SO_BINDTODEVICE
5449 if (!*args[cur_arg + 1]) {
5450 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5451 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005452 err_code |= ERR_ALERT | ERR_FATAL;
5453 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005454 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005455 free(curproxy->conn_src.iface_name);
5456 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5457 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005458 global.last_checks |= LSTCHK_NETADM;
5459#else
5460 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5461 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005462 err_code |= ERR_ALERT | ERR_FATAL;
5463 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005464#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005465 cur_arg += 2;
5466 continue;
5467 }
5468 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005469 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005470 err_code |= ERR_ALERT | ERR_FATAL;
5471 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005473 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005474 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5475 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5476 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005477 err_code |= ERR_ALERT | ERR_FATAL;
5478 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005480 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005481 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005482 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5483 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005484 err_code |= ERR_ALERT | ERR_FATAL;
5485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005486 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005487
5488 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005489 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005490 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005491 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005493 }
5494 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005495 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005496 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005497 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005498 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005500 }
5501 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005502 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005503 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005504 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005505 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005506 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005507 }
5508 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005509 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005510 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005511 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005512 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005513 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005514 }
5515 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005516 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005517 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005518 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005519 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005520 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005521 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005522 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005523 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005524 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005525 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005526 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005527 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005528 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005529 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005530 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005531 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005532 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005533 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005534 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005535
5536 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5537 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 +01005538 }
5539 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005540 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005541 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005542 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005543 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005544 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005545
5546 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5547 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 +01005548 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005549 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005550 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005551 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5552 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005553 err_code |= ERR_ALERT | ERR_FATAL;
5554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005555 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005556
5557 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005558 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005559 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005560 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005562 }
5563 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005564 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005565 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005566 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005567 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005569 }
5570 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005571 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005572 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005573 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005574 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005576 }
5577 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005578 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005579 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005580 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005581 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005583 }
5584 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005585 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005586 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005587 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005588 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005590 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005591 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005592 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005593 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005594 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005595 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005596 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005597 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005598 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005599 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005600
Willy Tarreaubaaee002006-06-26 02:48:02 +02005601 if (curproxy == &defproxy) {
5602 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005603 err_code |= ERR_ALERT | ERR_FATAL;
5604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005606 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005607 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005608
Willy Tarreaubaaee002006-06-26 02:48:02 +02005609 if (*(args[1]) == 0) {
5610 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005611 err_code |= ERR_ALERT | ERR_FATAL;
5612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005613 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005614
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005615 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005616 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5617 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5618 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005619 err_code |= ERR_ALERT | ERR_FATAL;
5620 goto out;
5621 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005622 err_code |= warnif_cond_conflicts(cond,
5623 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5624 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005625 }
5626 else if (*args[2]) {
5627 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5628 file, linenum, args[0], args[2]);
5629 err_code |= ERR_ALERT | ERR_FATAL;
5630 goto out;
5631 }
5632
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005633 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005634 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005635 wl->s = strdup(args[1]);
5636 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005637 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005638 }
5639 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005640 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005641 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5642 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005643 err_code |= ERR_ALERT | ERR_FATAL;
5644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005645 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005646
Willy Tarreauade5ec42010-01-28 19:33:49 +01005647 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005648 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005649 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005650 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005652 }
5653 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005654 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005655 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005656 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005657 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005658 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005659 }
5660 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005661 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005662 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005663 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005664 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005666 }
5667 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005668 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005669 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5670 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005671 err_code |= ERR_ALERT | ERR_FATAL;
5672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005673 }
5674
Willy Tarreauade5ec42010-01-28 19:33:49 +01005675 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005676 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005677 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005678 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005680 }
5681 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005682 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005683 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005684 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005685 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687 }
5688 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005689 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005690 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005691 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005692 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005693 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005694 }
5695 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005696 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005697
Willy Tarreaubaaee002006-06-26 02:48:02 +02005698 if (curproxy == &defproxy) {
5699 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005700 err_code |= ERR_ALERT | ERR_FATAL;
5701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005702 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005703 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005704 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705
Willy Tarreaubaaee002006-06-26 02:48:02 +02005706 if (*(args[1]) == 0) {
5707 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005708 err_code |= ERR_ALERT | ERR_FATAL;
5709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005710 }
5711
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005712 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005713 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5714 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5715 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005716 err_code |= ERR_ALERT | ERR_FATAL;
5717 goto out;
5718 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005719 err_code |= warnif_cond_conflicts(cond,
5720 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5721 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005722 }
5723 else if (*args[2]) {
5724 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5725 file, linenum, args[0], args[2]);
5726 err_code |= ERR_ALERT | ERR_FATAL;
5727 goto out;
5728 }
5729
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005730 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005731 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005732 wl->s = strdup(args[1]);
5733 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005734 }
5735 else if (!strcmp(args[0], "errorloc") ||
5736 !strcmp(args[0], "errorloc302") ||
5737 !strcmp(args[0], "errorloc303")) { /* error location */
5738 int errnum, errlen;
5739 char *err;
5740
Willy Tarreau977b8e42006-12-29 14:19:17 +01005741 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005742 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005743
Willy Tarreaubaaee002006-06-26 02:48:02 +02005744 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005745 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005746 err_code |= ERR_ALERT | ERR_FATAL;
5747 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005748 }
5749
5750 errnum = atol(args[1]);
5751 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005752 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5753 err = malloc(errlen);
5754 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005756 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5757 err = malloc(errlen);
5758 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005759 }
5760
Willy Tarreau0f772532006-12-23 20:51:41 +01005761 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5762 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005763 chunk_destroy(&curproxy->errmsg[rc]);
5764 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005765 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005766 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005767 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005768
5769 if (rc >= HTTP_ERR_SIZE) {
5770 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5771 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005772 free(err);
5773 }
5774 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005775 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5776 int errnum, errlen, fd;
5777 char *err;
5778 struct stat stat;
5779
5780 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005781 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005782
5783 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005784 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005785 err_code |= ERR_ALERT | ERR_FATAL;
5786 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005787 }
5788
5789 fd = open(args[2], O_RDONLY);
5790 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5791 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5792 file, linenum, args[2], args[1]);
5793 if (fd >= 0)
5794 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005795 err_code |= ERR_ALERT | ERR_FATAL;
5796 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005797 }
5798
Willy Tarreau27a674e2009-08-17 07:23:33 +02005799 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005800 errlen = stat.st_size;
5801 } else {
5802 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005803 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005804 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005805 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005806 }
5807
5808 err = malloc(errlen); /* malloc() must succeed during parsing */
5809 errnum = read(fd, err, errlen);
5810 if (errnum != errlen) {
5811 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5812 file, linenum, args[2], args[1]);
5813 close(fd);
5814 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005815 err_code |= ERR_ALERT | ERR_FATAL;
5816 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005817 }
5818 close(fd);
5819
5820 errnum = atol(args[1]);
5821 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5822 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005823 chunk_destroy(&curproxy->errmsg[rc]);
5824 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005825 break;
5826 }
5827 }
5828
5829 if (rc >= HTTP_ERR_SIZE) {
5830 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5831 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005832 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005833 free(err);
5834 }
5835 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005836 else if (!strcmp(args[0], "compression")) {
5837 struct comp *comp;
5838 if (curproxy->comp == NULL) {
5839 comp = calloc(1, sizeof(struct comp));
5840 curproxy->comp = comp;
5841 } else {
5842 comp = curproxy->comp;
5843 }
5844
5845 if (!strcmp(args[1], "algo")) {
5846 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005847 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005848
William Lallemand82fe75c2012-10-23 10:25:10 +02005849 cur_arg = 2;
5850 if (!*args[cur_arg]) {
5851 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5852 file, linenum, args[0]);
5853 err_code |= ERR_ALERT | ERR_FATAL;
5854 goto out;
5855 }
5856 while (*(args[cur_arg])) {
5857 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5858 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5859 file, linenum, args[0], args[cur_arg]);
5860 err_code |= ERR_ALERT | ERR_FATAL;
5861 goto out;
5862 }
William Lallemand552df672012-11-07 13:21:47 +01005863 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5864 curproxy->comp->algos->end(&ctx);
5865 } else {
5866 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5867 file, linenum, args[0], args[cur_arg]);
5868 err_code |= ERR_ALERT | ERR_FATAL;
5869 goto out;
5870 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005871 cur_arg ++;
5872 continue;
5873 }
5874 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005875 else if (!strcmp(args[1], "offload")) {
5876 comp->offload = 1;
5877 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005878 else if (!strcmp(args[1], "type")) {
5879 int cur_arg;
5880 cur_arg = 2;
5881 if (!*args[cur_arg]) {
5882 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5883 file, linenum, args[0]);
5884 err_code |= ERR_ALERT | ERR_FATAL;
5885 goto out;
5886 }
5887 while (*(args[cur_arg])) {
5888 comp_append_type(comp, args[cur_arg]);
5889 cur_arg ++;
5890 continue;
5891 }
5892 }
5893 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005894 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005895 file, linenum, args[0]);
5896 err_code |= ERR_ALERT | ERR_FATAL;
5897 goto out;
5898 }
5899 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005900 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005901 struct cfg_kw_list *kwl;
5902 int index;
5903
5904 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5905 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5906 if (kwl->kw[index].section != CFG_LISTEN)
5907 continue;
5908 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5909 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005910 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005911 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005912 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005913 err_code |= ERR_ALERT | ERR_FATAL;
5914 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005915 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005916 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005917 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005918 err_code |= ERR_WARN;
5919 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005920 }
Willy Tarreau93893792009-07-23 13:19:11 +02005921 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005922 }
5923 }
5924 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005925
Willy Tarreau6daf3432008-01-22 16:44:08 +01005926 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005927 err_code |= ERR_ALERT | ERR_FATAL;
5928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005929 }
Willy Tarreau93893792009-07-23 13:19:11 +02005930 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005931 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005932 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005933}
5934
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005935int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005936cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
5937{
5938#ifdef CONFIG_HAP_NS
5939 const char *err;
5940 const char *item = args[0];
5941
5942 if (!strcmp(item, "namespace_list")) {
5943 return 0;
5944 }
5945 else if (!strcmp(item, "namespace")) {
5946 size_t idx = 1;
5947 const char *current;
5948 while (*(current = args[idx++])) {
5949 err = invalid_char(current);
5950 if (err) {
5951 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5952 file, linenum, *err, item, current);
5953 return ERR_ALERT | ERR_FATAL;
5954 }
5955
5956 if (netns_store_lookup(current, strlen(current))) {
5957 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
5958 file, linenum, current);
5959 return ERR_ALERT | ERR_FATAL;
5960 }
5961 if (!netns_store_insert(current)) {
5962 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
5963 file, linenum, current);
5964 return ERR_ALERT | ERR_FATAL;
5965 }
5966 }
5967 }
5968
5969 return 0;
5970#else
5971 Alert("parsing [%s:%d]: namespace support is not compiled in.",
5972 file, linenum);
5973 return ERR_ALERT | ERR_FATAL;
5974#endif
5975}
5976
5977int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005978cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5979{
5980
5981 int err_code = 0;
5982 const char *err;
5983
5984 if (!strcmp(args[0], "userlist")) { /* new userlist */
5985 struct userlist *newul;
5986
5987 if (!*args[1]) {
5988 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5989 file, linenum, args[0]);
5990 err_code |= ERR_ALERT | ERR_FATAL;
5991 goto out;
5992 }
5993
5994 err = invalid_char(args[1]);
5995 if (err) {
5996 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5997 file, linenum, *err, args[0], args[1]);
5998 err_code |= ERR_ALERT | ERR_FATAL;
5999 goto out;
6000 }
6001
6002 for (newul = userlist; newul; newul = newul->next)
6003 if (!strcmp(newul->name, args[1])) {
6004 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6005 file, linenum, args[1]);
6006 err_code |= ERR_WARN;
6007 goto out;
6008 }
6009
6010 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6011 if (!newul) {
6012 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6013 err_code |= ERR_ALERT | ERR_ABORT;
6014 goto out;
6015 }
6016
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006017 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006018 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006019 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6020 err_code |= ERR_ALERT | ERR_ABORT;
6021 goto out;
6022 }
6023
6024 newul->next = userlist;
6025 userlist = newul;
6026
6027 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006028 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006029 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006030 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006031
6032 if (!*args[1]) {
6033 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6034 file, linenum, args[0]);
6035 err_code |= ERR_ALERT | ERR_FATAL;
6036 goto out;
6037 }
6038
6039 err = invalid_char(args[1]);
6040 if (err) {
6041 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6042 file, linenum, *err, args[0], args[1]);
6043 err_code |= ERR_ALERT | ERR_FATAL;
6044 goto out;
6045 }
6046
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006047 for (ag = userlist->groups; ag; ag = ag->next)
6048 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006049 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6050 file, linenum, args[1], userlist->name);
6051 err_code |= ERR_ALERT;
6052 goto out;
6053 }
6054
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006055 ag = calloc(1, sizeof(*ag));
6056 if (!ag) {
6057 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6058 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006059 goto out;
6060 }
6061
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006062 ag->name = strdup(args[1]);
6063 if (!ag) {
6064 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6065 err_code |= ERR_ALERT | ERR_ABORT;
6066 goto out;
6067 }
6068
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006069 cur_arg = 2;
6070
6071 while (*args[cur_arg]) {
6072 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006073 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006074 cur_arg += 2;
6075 continue;
6076 } else {
6077 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6078 file, linenum, args[0]);
6079 err_code |= ERR_ALERT | ERR_FATAL;
6080 goto out;
6081 }
6082 }
6083
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006084 ag->next = userlist->groups;
6085 userlist->groups = ag;
6086
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006087 } else if (!strcmp(args[0], "user")) { /* new user */
6088 struct auth_users *newuser;
6089 int cur_arg;
6090
6091 if (!*args[1]) {
6092 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6093 file, linenum, args[0]);
6094 err_code |= ERR_ALERT | ERR_FATAL;
6095 goto out;
6096 }
6097
6098 for (newuser = userlist->users; newuser; newuser = newuser->next)
6099 if (!strcmp(newuser->user, args[1])) {
6100 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6101 file, linenum, args[1], userlist->name);
6102 err_code |= ERR_ALERT;
6103 goto out;
6104 }
6105
6106 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6107 if (!newuser) {
6108 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6109 err_code |= ERR_ALERT | ERR_ABORT;
6110 goto out;
6111 }
6112
6113 newuser->user = strdup(args[1]);
6114
6115 newuser->next = userlist->users;
6116 userlist->users = newuser;
6117
6118 cur_arg = 2;
6119
6120 while (*args[cur_arg]) {
6121 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006122#ifdef CONFIG_HAP_CRYPT
6123 if (!crypt("", args[cur_arg + 1])) {
6124 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6125 file, linenum, newuser->user);
6126 err_code |= ERR_ALERT | ERR_FATAL;
6127 goto out;
6128 }
6129#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006130 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6131 file, linenum);
6132 err_code |= ERR_ALERT;
6133#endif
6134 newuser->pass = strdup(args[cur_arg + 1]);
6135 cur_arg += 2;
6136 continue;
6137 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6138 newuser->pass = strdup(args[cur_arg + 1]);
6139 newuser->flags |= AU_O_INSECURE;
6140 cur_arg += 2;
6141 continue;
6142 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006143 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006144 cur_arg += 2;
6145 continue;
6146 } else {
6147 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6148 file, linenum, args[0]);
6149 err_code |= ERR_ALERT | ERR_FATAL;
6150 goto out;
6151 }
6152 }
6153 } else {
6154 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6155 err_code |= ERR_ALERT | ERR_FATAL;
6156 }
6157
6158out:
6159 return err_code;
6160}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006161
6162/*
6163 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006164 * Returns the error code, 0 if OK, or any combination of :
6165 * - ERR_ABORT: must abort ASAP
6166 * - ERR_FATAL: we can continue parsing but not start the service
6167 * - ERR_WARN: a warning has been emitted
6168 * - ERR_ALERT: an alert has been emitted
6169 * Only the two first ones can stop processing, the two others are just
6170 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006171 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006172int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006173{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006174 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006175 FILE *f;
6176 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006177 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006178 struct cfg_section *cs = NULL;
6179 struct cfg_section *ics;
6180
6181 /* Register internal sections */
6182 if (!cfg_register_section("listen", cfg_parse_listen) ||
6183 !cfg_register_section("frontend", cfg_parse_listen) ||
6184 !cfg_register_section("backend", cfg_parse_listen) ||
6185 !cfg_register_section("ruleset", cfg_parse_listen) ||
6186 !cfg_register_section("defaults", cfg_parse_listen) ||
6187 !cfg_register_section("global", cfg_parse_global) ||
6188 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006189 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006190 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006191 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006192 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006193
Willy Tarreaubaaee002006-06-26 02:48:02 +02006194 if ((f=fopen(file,"r")) == NULL)
6195 return -1;
6196
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006197 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006198 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006199 char *end;
6200 char *args[MAX_LINE_ARGS + 1];
6201 char *line = thisline;
6202
Willy Tarreaubaaee002006-06-26 02:48:02 +02006203 linenum++;
6204
6205 end = line + strlen(line);
6206
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006207 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6208 /* Check if we reached the limit and the last char is not \n.
6209 * Watch out for the last line without the terminating '\n'!
6210 */
6211 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006212 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006213 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006214 }
6215
Willy Tarreaubaaee002006-06-26 02:48:02 +02006216 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006217 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006218 line++;
6219
6220 arg = 0;
6221 args[arg] = line;
6222
6223 while (*line && arg < MAX_LINE_ARGS) {
6224 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6225 * C equivalent value. Other combinations left unchanged (eg: \1).
6226 */
6227 if (*line == '\\') {
6228 int skip = 0;
6229 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6230 *line = line[1];
6231 skip = 1;
6232 }
6233 else if (line[1] == 'r') {
6234 *line = '\r';
6235 skip = 1;
6236 }
6237 else if (line[1] == 'n') {
6238 *line = '\n';
6239 skip = 1;
6240 }
6241 else if (line[1] == 't') {
6242 *line = '\t';
6243 skip = 1;
6244 }
6245 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006246 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006247 unsigned char hex1, hex2;
6248 hex1 = toupper(line[2]) - '0';
6249 hex2 = toupper(line[3]) - '0';
6250 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6251 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6252 *line = (hex1<<4) + hex2;
6253 skip = 3;
6254 }
6255 else {
6256 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006257 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006258 }
6259 }
6260 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006261 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006262 end -= skip;
6263 }
6264 line++;
6265 }
6266 else if (*line == '#' || *line == '\n' || *line == '\r') {
6267 /* end of string, end of loop */
6268 *line = 0;
6269 break;
6270 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006271 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006272 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006273 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006274 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006275 line++;
6276 args[++arg] = line;
6277 }
6278 else {
6279 line++;
6280 }
6281 }
6282
6283 /* empty line */
6284 if (!**args)
6285 continue;
6286
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006287 if (*line) {
6288 /* we had to stop due to too many args.
6289 * Let's terminate the string, print the offending part then cut the
6290 * last arg.
6291 */
6292 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6293 line++;
6294 *line = '\0';
6295
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006296 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006297 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006298 err_code |= ERR_ALERT | ERR_FATAL;
6299 args[arg] = line;
6300 }
6301
Willy Tarreau540abe42007-05-02 20:50:16 +02006302 /* zero out remaining args and ensure that at least one entry
6303 * is zeroed out.
6304 */
6305 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006306 args[arg] = line;
6307 }
6308
Willy Tarreau3842f002009-06-14 11:39:52 +02006309 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006310 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006311 char *tmp;
6312
Willy Tarreau3842f002009-06-14 11:39:52 +02006313 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006314 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006315 for (arg=0; *args[arg+1]; arg++)
6316 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006317 *tmp = '\0'; // fix the next arg to \0
6318 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006319 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006320 else if (!strcmp(args[0], "default")) {
6321 kwm = KWM_DEF;
6322 for (arg=0; *args[arg+1]; arg++)
6323 args[arg] = args[arg+1]; // shift args after inversion
6324 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006325
William Lallemand0f99e342011-10-12 17:50:54 +02006326 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6327 strcmp(args[0], "log") != 0) {
6328 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006329 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006330 }
6331
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006332 /* detect section start */
6333 list_for_each_entry(ics, &sections, list) {
6334 if (strcmp(args[0], ics->section_name) == 0) {
6335 cursection = ics->section_name;
6336 cs = ics;
6337 break;
6338 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006339 }
6340
Willy Tarreaubaaee002006-06-26 02:48:02 +02006341 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006342 if (cs)
6343 err_code |= cs->section_parser(file, linenum, args, kwm);
6344 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006345 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006346 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006347 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006348
6349 if (err_code & ERR_ABORT)
6350 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006351 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006352 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006353 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006354 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006355}
6356
Willy Tarreau64ab6072014-09-16 12:17:36 +02006357/* This function propagates processes from frontend <from> to backend <to> so
6358 * that it is always guaranteed that a backend pointed to by a frontend is
6359 * bound to all of its processes. After that, if the target is a "listen"
6360 * instance, the function recursively descends the target's own targets along
6361 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6362 * checked first to ensure that <to> is already bound to all processes of
6363 * <from>, there is no risk of looping and we ensure to follow the shortest
6364 * path to the destination.
6365 *
6366 * It is possible to set <to> to NULL for the first call so that the function
6367 * takes care of visiting the initial frontend in <from>.
6368 *
6369 * It is important to note that the function relies on the fact that all names
6370 * have already been resolved.
6371 */
6372void propagate_processes(struct proxy *from, struct proxy *to)
6373{
6374 struct switching_rule *rule;
6375 struct hdr_exp *exp;
6376
6377 if (to) {
6378 /* check whether we need to go down */
6379 if (from->bind_proc &&
6380 (from->bind_proc & to->bind_proc) == from->bind_proc)
6381 return;
6382
6383 if (!from->bind_proc && !to->bind_proc)
6384 return;
6385
6386 to->bind_proc = from->bind_proc ?
6387 (to->bind_proc | from->bind_proc) : 0;
6388
6389 /* now propagate down */
6390 from = to;
6391 }
6392
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006393 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006394 return;
6395
Willy Tarreauf6b70012014-12-18 14:00:43 +01006396 if (from->state == PR_STSTOPPED)
6397 return;
6398
Willy Tarreau64ab6072014-09-16 12:17:36 +02006399 /* default_backend */
6400 if (from->defbe.be)
6401 propagate_processes(from, from->defbe.be);
6402
6403 /* use_backend */
6404 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006405 if (rule->dynamic)
6406 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006407 to = rule->be.backend;
6408 propagate_processes(from, to);
6409 }
6410
6411 /* reqsetbe */
6412 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6413 if (exp->action != ACT_SETBE)
6414 continue;
6415 to = (struct proxy *)exp->replace;
6416 propagate_processes(from, to);
6417 }
6418}
6419
Willy Tarreaubb925012009-07-23 13:36:36 +02006420/*
6421 * Returns the error code, 0 if OK, or any combination of :
6422 * - ERR_ABORT: must abort ASAP
6423 * - ERR_FATAL: we can continue parsing but not start the service
6424 * - ERR_WARN: a warning has been emitted
6425 * - ERR_ALERT: an alert has been emitted
6426 * Only the two first ones can stop processing, the two others are just
6427 * indicators.
6428 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006429int check_config_validity()
6430{
6431 int cfgerr = 0;
6432 struct proxy *curproxy = NULL;
6433 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006434 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006435 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006436 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006437
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006438 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006439 /*
6440 * Now, check for the integrity of all that we have collected.
6441 */
6442
6443 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006444 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006445
Willy Tarreau193b8c62012-11-22 00:17:38 +01006446 if (!global.tune.max_http_hdr)
6447 global.tune.max_http_hdr = MAX_HTTP_HDR;
6448
6449 if (!global.tune.cookie_len)
6450 global.tune.cookie_len = CAPTURE_LEN;
6451
6452 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6453
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006454 /* Post initialisation of the users and groups lists. */
6455 err_code = userlist_postinit();
6456 if (err_code != ERR_NONE)
6457 goto out;
6458
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006459 /* first, we will invert the proxy list order */
6460 curproxy = NULL;
6461 while (proxy) {
6462 struct proxy *next;
6463
6464 next = proxy->next;
6465 proxy->next = curproxy;
6466 curproxy = proxy;
6467 if (!next)
6468 break;
6469 proxy = next;
6470 }
6471
Willy Tarreau419ead82014-09-16 13:41:21 +02006472 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006473 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006474 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006475 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006476 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006477 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006478 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006479 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006480
Willy Tarreau050536d2012-10-04 08:47:34 +02006481 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006482 /* proxy ID not set, use automatic numbering with first
6483 * spare entry starting with next_pxid.
6484 */
6485 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6486 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6487 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006488 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006489 next_pxid++;
6490
Willy Tarreau55ea7572007-06-17 19:56:27 +02006491
Willy Tarreaubaaee002006-06-26 02:48:02 +02006492 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006493 /* ensure we don't keep listeners uselessly bound */
6494 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02006495 free((void *)curproxy->table.peers.name);
6496 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006497 continue;
6498 }
6499
Willy Tarreau102df612014-05-07 23:56:38 +02006500 /* Check multi-process mode compatibility for the current proxy */
6501
6502 if (curproxy->bind_proc) {
6503 /* an explicit bind-process was specified, let's check how many
6504 * processes remain.
6505 */
6506 nbproc = popcount(curproxy->bind_proc);
6507
6508 curproxy->bind_proc &= nbits(global.nbproc);
6509 if (!curproxy->bind_proc && nbproc == 1) {
6510 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);
6511 curproxy->bind_proc = 1;
6512 }
6513 else if (!curproxy->bind_proc && nbproc > 1) {
6514 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);
6515 curproxy->bind_proc = 0;
6516 }
6517 }
6518
Willy Tarreau3d209582014-05-09 17:06:11 +02006519 /* check and reduce the bind-proc of each listener */
6520 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6521 unsigned long mask;
6522
6523 if (!bind_conf->bind_proc)
6524 continue;
6525
6526 mask = nbits(global.nbproc);
6527 if (curproxy->bind_proc)
6528 mask &= curproxy->bind_proc;
6529 /* mask cannot be null here thanks to the previous checks */
6530
6531 nbproc = popcount(bind_conf->bind_proc);
6532 bind_conf->bind_proc &= mask;
6533
6534 if (!bind_conf->bind_proc && nbproc == 1) {
6535 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",
6536 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6537 bind_conf->bind_proc = mask & ~(mask - 1);
6538 }
6539 else if (!bind_conf->bind_proc && nbproc > 1) {
6540 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",
6541 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6542 bind_conf->bind_proc = 0;
6543 }
6544 }
6545
Willy Tarreau102df612014-05-07 23:56:38 +02006546 if (global.nbproc > 1 && curproxy->table.peers.name) {
6547 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6548 curproxy->id);
6549 cfgerr++;
6550 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006551
Willy Tarreauff01a212009-03-15 13:46:16 +01006552 switch (curproxy->mode) {
6553 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006554 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006555 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006556 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6557 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006558 cfgerr++;
6559 }
6560
6561 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006562 Warning("config : servers will be ignored for %s '%s'.\n",
6563 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006564 break;
6565
6566 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006567 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006568 break;
6569
6570 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006571 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006572 break;
6573 }
6574
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006575 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006576 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006577 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006578 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6579 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006580 cfgerr++;
6581 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006582#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006583 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006584 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6585 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006586 cfgerr++;
6587 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006588#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006589 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006590 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6591 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006592 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006593 }
6594 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006595 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006596 /* If no LB algo is set in a backend, and we're not in
6597 * transparent mode, dispatch mode nor proxy mode, we
6598 * want to use balance roundrobin by default.
6599 */
6600 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6601 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006602 }
6603 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006604
Willy Tarreau1620ec32011-08-06 17:05:02 +02006605 if (curproxy->options & PR_O_DISPATCH)
6606 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6607 else if (curproxy->options & PR_O_HTTP_PROXY)
6608 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6609 else if (curproxy->options & PR_O_TRANSP)
6610 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006611
Willy Tarreau1620ec32011-08-06 17:05:02 +02006612 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6613 if (curproxy->options & PR_O_DISABLE404) {
6614 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6615 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6616 err_code |= ERR_WARN;
6617 curproxy->options &= ~PR_O_DISABLE404;
6618 }
6619 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6620 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6621 "send-state", proxy_type_str(curproxy), curproxy->id);
6622 err_code |= ERR_WARN;
6623 curproxy->options &= ~PR_O2_CHK_SNDST;
6624 }
Willy Tarreauef781042010-01-27 11:53:01 +01006625 }
6626
Simon Horman98637e52014-06-20 12:30:16 +09006627 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6628 if (!global.external_check) {
6629 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6630 curproxy->id, "option external-check");
6631 cfgerr++;
6632 }
6633 if (!curproxy->check_command) {
6634 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6635 curproxy->id, "option external-check");
6636 cfgerr++;
6637 }
6638 }
6639
Simon Horman64e34162015-02-06 11:11:57 +09006640 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006641 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
6642 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09006643 "'email-alert from', 'email-alert level' 'email-alert mailer', "
6644 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006645 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
6646 "to be present).\n",
6647 proxy_type_str(curproxy), curproxy->id);
6648 err_code |= ERR_WARN;
6649 free_email_alert(curproxy);
6650 }
6651 if (!curproxy->email_alert.myhostname)
6652 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09006653 }
6654
Simon Horman98637e52014-06-20 12:30:16 +09006655 if (curproxy->check_command) {
6656 int clear = 0;
6657 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6658 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6659 "external-check command", proxy_type_str(curproxy), curproxy->id);
6660 err_code |= ERR_WARN;
6661 clear = 1;
6662 }
6663 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6664 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6665 curproxy->id, "external-check command");
6666 cfgerr++;
6667 }
6668 if (clear) {
6669 free(curproxy->check_command);
6670 curproxy->check_command = NULL;
6671 }
6672 }
6673
6674 if (curproxy->check_path) {
6675 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6676 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6677 "external-check path", proxy_type_str(curproxy), curproxy->id);
6678 err_code |= ERR_WARN;
6679 free(curproxy->check_path);
6680 curproxy->check_path = NULL;
6681 }
6682 }
6683
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006684 /* if a default backend was specified, let's find it */
6685 if (curproxy->defbe.name) {
6686 struct proxy *target;
6687
Alex Williams96532db2009-11-01 21:27:13 -05006688 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006689 if (!target) {
6690 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6691 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006692 cfgerr++;
6693 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006694 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6695 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006696 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006697 } else {
6698 free(curproxy->defbe.name);
6699 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006700
6701 /* Emit a warning if this proxy also has some servers */
6702 if (curproxy->srv) {
6703 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6704 curproxy->id);
6705 err_code |= ERR_WARN;
6706 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006707 }
6708 }
6709
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006710 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006711 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6712 /* map jump target for ACT_SETBE in req_rep chain */
6713 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006714 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006715 struct proxy *target;
6716
Willy Tarreaua496b602006-12-17 23:15:24 +01006717 if (exp->action != ACT_SETBE)
6718 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006719
Alex Williams96532db2009-11-01 21:27:13 -05006720 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006721 if (!target) {
6722 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6723 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006724 cfgerr++;
6725 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006726 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6727 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006728 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006729 } else {
6730 free((void *)exp->replace);
6731 exp->replace = (const char *)target;
6732 }
6733 }
6734 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006735
6736 /* find the target proxy for 'use_backend' rules */
6737 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006738 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006739 struct logformat_node *node;
6740 char *pxname;
6741
6742 /* Try to parse the string as a log format expression. If the result
6743 * of the parsing is only one entry containing a simple string, then
6744 * it's a standard string corresponding to a static rule, thus the
6745 * parsing is cancelled and be.name is restored to be resolved.
6746 */
6747 pxname = rule->be.name;
6748 LIST_INIT(&rule->be.expr);
6749 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6750 curproxy->conf.args.file, curproxy->conf.args.line);
6751 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6752
6753 if (!LIST_ISEMPTY(&rule->be.expr)) {
6754 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6755 rule->dynamic = 1;
6756 free(pxname);
6757 continue;
6758 }
6759 /* simple string: free the expression and fall back to static rule */
6760 free(node->arg);
6761 free(node);
6762 }
6763
6764 rule->dynamic = 0;
6765 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006766
Alex Williams96532db2009-11-01 21:27:13 -05006767 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006768
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006769 if (!target) {
6770 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6771 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006772 cfgerr++;
6773 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006774 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6775 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006776 cfgerr++;
6777 } else {
6778 free((void *)rule->be.name);
6779 rule->be.backend = target;
6780 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006781 }
6782
Willy Tarreau64ab6072014-09-16 12:17:36 +02006783 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006784 list_for_each_entry(srule, &curproxy->server_rules, list) {
6785 struct server *target = findserver(curproxy, srule->srv.name);
6786
6787 if (!target) {
6788 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6789 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6790 cfgerr++;
6791 continue;
6792 }
6793 free((void *)srule->srv.name);
6794 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006795 }
6796
Emeric Brunb982a3d2010-01-04 15:45:53 +01006797 /* find the target table for 'stick' rules */
6798 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6799 struct proxy *target;
6800
Emeric Brun1d33b292010-01-04 15:47:17 +01006801 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6802 if (mrule->flags & STK_IS_STORE)
6803 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6804
Emeric Brunb982a3d2010-01-04 15:45:53 +01006805 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006806 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006807 else
6808 target = curproxy;
6809
6810 if (!target) {
6811 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6812 curproxy->id, mrule->table.name);
6813 cfgerr++;
6814 }
6815 else if (target->table.size == 0) {
6816 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6817 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6818 cfgerr++;
6819 }
Willy Tarreau12785782012-04-27 21:37:17 +02006820 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6821 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006822 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6823 cfgerr++;
6824 }
6825 else {
6826 free((void *)mrule->table.name);
6827 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006828 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006829 }
6830 }
6831
6832 /* find the target table for 'store response' rules */
6833 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6834 struct proxy *target;
6835
Emeric Brun1d33b292010-01-04 15:47:17 +01006836 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6837
Emeric Brunb982a3d2010-01-04 15:45:53 +01006838 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006839 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006840 else
6841 target = curproxy;
6842
6843 if (!target) {
6844 Alert("Proxy '%s': unable to find store table '%s'.\n",
6845 curproxy->id, mrule->table.name);
6846 cfgerr++;
6847 }
6848 else if (target->table.size == 0) {
6849 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6850 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6851 cfgerr++;
6852 }
Willy Tarreau12785782012-04-27 21:37:17 +02006853 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6854 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006855 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6856 cfgerr++;
6857 }
6858 else {
6859 free((void *)mrule->table.name);
6860 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006861 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006862 }
6863 }
6864
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006865 /* find the target table for 'tcp-request' layer 4 rules */
6866 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6867 struct proxy *target;
6868
Willy Tarreaub4c84932013-07-23 19:15:30 +02006869 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006870 continue;
6871
6872 if (trule->act_prm.trk_ctr.table.n)
6873 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6874 else
6875 target = curproxy;
6876
6877 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006878 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6879 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006880 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006881 cfgerr++;
6882 }
6883 else if (target->table.size == 0) {
6884 Alert("Proxy '%s': table '%s' used but not configured.\n",
6885 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6886 cfgerr++;
6887 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006888 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6889 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6890 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 +01006891 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006892 cfgerr++;
6893 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006894 else {
6895 free(trule->act_prm.trk_ctr.table.n);
6896 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006897 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006898 * to pass a list of counters to track and allocate them right here using
6899 * stktable_alloc_data_type().
6900 */
6901 }
6902 }
6903
Willy Tarreaud1f96522010-08-03 19:34:32 +02006904 /* find the target table for 'tcp-request' layer 6 rules */
6905 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6906 struct proxy *target;
6907
Willy Tarreaub4c84932013-07-23 19:15:30 +02006908 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006909 continue;
6910
6911 if (trule->act_prm.trk_ctr.table.n)
6912 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6913 else
6914 target = curproxy;
6915
6916 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006917 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6918 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006919 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006920 cfgerr++;
6921 }
6922 else if (target->table.size == 0) {
6923 Alert("Proxy '%s': table '%s' used but not configured.\n",
6924 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6925 cfgerr++;
6926 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006927 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6928 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6929 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 +01006930 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006931 cfgerr++;
6932 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006933 else {
6934 free(trule->act_prm.trk_ctr.table.n);
6935 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006936 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006937 * to pass a list of counters to track and allocate them right here using
6938 * stktable_alloc_data_type().
6939 */
6940 }
6941 }
6942
Willy Tarreau09448f72014-06-25 18:12:15 +02006943 /* find the target table for 'http-request' layer 7 rules */
6944 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6945 struct proxy *target;
6946
6947 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6948 continue;
6949
6950 if (hrqrule->act_prm.trk_ctr.table.n)
6951 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6952 else
6953 target = curproxy;
6954
6955 if (!target) {
6956 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6957 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6958 http_req_trk_idx(hrqrule->action));
6959 cfgerr++;
6960 }
6961 else if (target->table.size == 0) {
6962 Alert("Proxy '%s': table '%s' used but not configured.\n",
6963 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6964 cfgerr++;
6965 }
6966 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6967 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6968 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6969 http_req_trk_idx(hrqrule->action));
6970 cfgerr++;
6971 }
6972 else {
6973 free(hrqrule->act_prm.trk_ctr.table.n);
6974 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6975 /* Note: if we decide to enhance the track-sc syntax, we may be able
6976 * to pass a list of counters to track and allocate them right here using
6977 * stktable_alloc_data_type().
6978 */
6979 }
6980 }
6981
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006982 /* move any "block" rules at the beginning of the http-request rules */
6983 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6984 /* insert block_rules into http_req_rules at the beginning */
6985 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6986 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6987 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6988 curproxy->http_req_rules.n = curproxy->block_rules.n;
6989 LIST_INIT(&curproxy->block_rules);
6990 }
6991
Emeric Brun32da3c42010-09-23 18:39:19 +02006992 if (curproxy->table.peers.name) {
6993 struct peers *curpeers = peers;
6994
6995 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6996 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6997 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006998 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006999 break;
7000 }
7001 }
7002
7003 if (!curpeers) {
7004 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7005 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007006 free((void *)curproxy->table.peers.name);
7007 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007008 cfgerr++;
7009 }
7010 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007011 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7012 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007013 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007014 cfgerr++;
7015 }
7016 }
7017
Simon Horman9dc49962015-01-30 11:22:59 +09007018
7019 if (curproxy->email_alert.mailers.name) {
7020 struct mailers *curmailers = mailers;
7021
7022 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7023 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7024 free(curproxy->email_alert.mailers.name);
7025 curproxy->email_alert.mailers.m = curmailers;
7026 curmailers->users++;
7027 break;
7028 }
7029 }
7030
7031 if (!curmailers) {
7032 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7033 curproxy->id, curproxy->email_alert.mailers.name);
7034 free_email_alert(curproxy);
7035 cfgerr++;
7036 }
7037 }
7038
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007039 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007040 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007041 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7042 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7043 "proxy", curproxy->id);
7044 cfgerr++;
7045 goto out_uri_auth_compat;
7046 }
7047
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007048 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007049 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007050 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007051 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007052
Willy Tarreau95fa4692010-02-01 13:05:50 +01007053 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7054 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007055
7056 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007057 uri_auth_compat_req[i++] = "realm";
7058 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7059 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007060
Willy Tarreau95fa4692010-02-01 13:05:50 +01007061 uri_auth_compat_req[i++] = "unless";
7062 uri_auth_compat_req[i++] = "{";
7063 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7064 uri_auth_compat_req[i++] = "}";
7065 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007066
Willy Tarreauff011f22011-01-06 17:51:27 +01007067 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7068 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007069 cfgerr++;
7070 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007071 }
7072
Willy Tarreauff011f22011-01-06 17:51:27 +01007073 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007074
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007075 if (curproxy->uri_auth->auth_realm) {
7076 free(curproxy->uri_auth->auth_realm);
7077 curproxy->uri_auth->auth_realm = NULL;
7078 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007079
7080 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007081 }
7082out_uri_auth_compat:
7083
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007084 /* compile the log format */
7085 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007086 if (curproxy->conf.logformat_string != default_http_log_format &&
7087 curproxy->conf.logformat_string != default_tcp_log_format &&
7088 curproxy->conf.logformat_string != clf_http_log_format)
7089 free(curproxy->conf.logformat_string);
7090 curproxy->conf.logformat_string = NULL;
7091 free(curproxy->conf.lfs_file);
7092 curproxy->conf.lfs_file = NULL;
7093 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007094 }
7095
Willy Tarreau62a61232013-04-12 18:13:46 +02007096 if (curproxy->conf.logformat_string) {
7097 curproxy->conf.args.ctx = ARGC_LOG;
7098 curproxy->conf.args.file = curproxy->conf.lfs_file;
7099 curproxy->conf.args.line = curproxy->conf.lfs_line;
7100 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007101 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007102 curproxy->conf.args.file = NULL;
7103 curproxy->conf.args.line = 0;
7104 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007105
Willy Tarreau62a61232013-04-12 18:13:46 +02007106 if (curproxy->conf.uniqueid_format_string) {
7107 curproxy->conf.args.ctx = ARGC_UIF;
7108 curproxy->conf.args.file = curproxy->conf.uif_file;
7109 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007110 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007111 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007112 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007113 curproxy->conf.args.file = NULL;
7114 curproxy->conf.args.line = 0;
7115 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007116
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007117 /* only now we can check if some args remain unresolved.
7118 * This must be done after the users and groups resolution.
7119 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007120 cfgerr += smp_resolve_args(curproxy);
7121 if (!cfgerr)
7122 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007123
Willy Tarreau2738a142006-07-08 17:28:09 +02007124 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007125 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007126 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007127 (!curproxy->timeout.connect ||
7128 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007129 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007130 " | While not properly invalid, you will certainly encounter various problems\n"
7131 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007132 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007133 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007134 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007135 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007136
Willy Tarreau1fa31262007-12-03 00:36:16 +01007137 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7138 * We must still support older configurations, so let's find out whether those
7139 * parameters have been set or must be copied from contimeouts.
7140 */
7141 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007142 if (!curproxy->timeout.tarpit ||
7143 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007144 /* tarpit timeout not set. We search in the following order:
7145 * default.tarpit, curr.connect, default.connect.
7146 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007147 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007148 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007149 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007150 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007151 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007152 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007153 }
7154 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007155 (!curproxy->timeout.queue ||
7156 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007157 /* queue timeout not set. We search in the following order:
7158 * default.queue, curr.connect, default.connect.
7159 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007160 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007161 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007162 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007163 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007164 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007165 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007166 }
7167 }
7168
Willy Tarreau1620ec32011-08-06 17:05:02 +02007169 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007170 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7171 curproxy->check_req = (char *)malloc(curproxy->check_len);
7172 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007173 }
7174
Willy Tarreau215663d2014-06-13 18:30:23 +02007175 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7176 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7177 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7178 proxy_type_str(curproxy), curproxy->id);
7179 err_code |= ERR_WARN;
7180 }
7181
Willy Tarreau193b8c62012-11-22 00:17:38 +01007182 /* ensure that cookie capture length is not too large */
7183 if (curproxy->capture_len >= global.tune.cookie_len) {
7184 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7185 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7186 err_code |= ERR_WARN;
7187 curproxy->capture_len = global.tune.cookie_len - 1;
7188 }
7189
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007190 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007191 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007192 curproxy->req_cap_pool = create_pool("ptrcap",
7193 curproxy->nb_req_cap * sizeof(char *),
7194 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007195 }
7196
7197 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007198 curproxy->rsp_cap_pool = create_pool("ptrcap",
7199 curproxy->nb_rsp_cap * sizeof(char *),
7200 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007201 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007202
Willy Tarreaubaaee002006-06-26 02:48:02 +02007203 /* first, we will invert the servers list order */
7204 newsrv = NULL;
7205 while (curproxy->srv) {
7206 struct server *next;
7207
7208 next = curproxy->srv->next;
7209 curproxy->srv->next = newsrv;
7210 newsrv = curproxy->srv;
7211 if (!next)
7212 break;
7213 curproxy->srv = next;
7214 }
7215
Willy Tarreau17edc812014-01-03 12:14:34 +01007216 /* Check that no server name conflicts. This causes trouble in the stats.
7217 * We only emit a warning for the first conflict affecting each server,
7218 * in order to avoid combinatory explosion if all servers have the same
7219 * name. We do that only for servers which do not have an explicit ID,
7220 * because these IDs were made also for distinguishing them and we don't
7221 * want to annoy people who correctly manage them.
7222 */
7223 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7224 struct server *other_srv;
7225
7226 if (newsrv->puid)
7227 continue;
7228
7229 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7230 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7231 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7232 newsrv->conf.file, newsrv->conf.line,
7233 proxy_type_str(curproxy), curproxy->id,
7234 newsrv->id, other_srv->conf.line);
7235 break;
7236 }
7237 }
7238 }
7239
Willy Tarreaudd701652010-05-25 23:03:02 +02007240 /* assign automatic UIDs to servers which don't have one yet */
7241 next_id = 1;
7242 newsrv = curproxy->srv;
7243 while (newsrv != NULL) {
7244 if (!newsrv->puid) {
7245 /* server ID not set, use automatic numbering with first
7246 * spare entry starting with next_svid.
7247 */
7248 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7249 newsrv->conf.id.key = newsrv->puid = next_id;
7250 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7251 }
7252 next_id++;
7253 newsrv = newsrv->next;
7254 }
7255
Willy Tarreau20697042007-11-15 23:26:18 +01007256 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007257 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007258
Willy Tarreau62c3be22012-01-20 13:12:32 +01007259 /*
7260 * If this server supports a maxconn parameter, it needs a dedicated
7261 * tasks to fill the emptied slots when a connection leaves.
7262 * Also, resolve deferred tracking dependency if needed.
7263 */
7264 newsrv = curproxy->srv;
7265 while (newsrv != NULL) {
7266 if (newsrv->minconn > newsrv->maxconn) {
7267 /* Only 'minconn' was specified, or it was higher than or equal
7268 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7269 * this will avoid further useless expensive computations.
7270 */
7271 newsrv->maxconn = newsrv->minconn;
7272 } else if (newsrv->maxconn && !newsrv->minconn) {
7273 /* minconn was not specified, so we set it to maxconn */
7274 newsrv->minconn = newsrv->maxconn;
7275 }
7276
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007277#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007278 if (newsrv->use_ssl || newsrv->check.use_ssl)
7279 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007280#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007281
Willy Tarreau2f075e92013-12-03 11:11:34 +01007282 /* set the check type on the server */
7283 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7284
Willy Tarreau62c3be22012-01-20 13:12:32 +01007285 if (newsrv->trackit) {
7286 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007287 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007288 char *pname, *sname;
7289
7290 pname = newsrv->trackit;
7291 sname = strrchr(pname, '/');
7292
7293 if (sname)
7294 *sname++ = '\0';
7295 else {
7296 sname = pname;
7297 pname = NULL;
7298 }
7299
7300 if (pname) {
7301 px = findproxy(pname, PR_CAP_BE);
7302 if (!px) {
7303 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7304 proxy_type_str(curproxy), curproxy->id,
7305 newsrv->id, pname);
7306 cfgerr++;
7307 goto next_srv;
7308 }
7309 } else
7310 px = curproxy;
7311
7312 srv = findserver(px, sname);
7313 if (!srv) {
7314 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7315 proxy_type_str(curproxy), curproxy->id,
7316 newsrv->id, sname);
7317 cfgerr++;
7318 goto next_srv;
7319 }
7320
Willy Tarreau32091232014-05-16 13:52:00 +02007321 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7322 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7323 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007324 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007325 "tracking as it does not have any check nor agent enabled.\n",
7326 proxy_type_str(curproxy), curproxy->id,
7327 newsrv->id, px->id, srv->id);
7328 cfgerr++;
7329 goto next_srv;
7330 }
7331
7332 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7333
7334 if (loop) {
7335 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7336 "belongs to a tracking chain looping back to %s/%s.\n",
7337 proxy_type_str(curproxy), curproxy->id,
7338 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007339 cfgerr++;
7340 goto next_srv;
7341 }
7342
7343 if (curproxy != px &&
7344 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7345 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7346 "tracking: disable-on-404 option inconsistency.\n",
7347 proxy_type_str(curproxy), curproxy->id,
7348 newsrv->id, px->id, srv->id);
7349 cfgerr++;
7350 goto next_srv;
7351 }
7352
7353 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007354 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007355 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007356 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007357 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007358 }
7359
7360 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007361 newsrv->tracknext = srv->trackers;
7362 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007363
7364 free(newsrv->trackit);
7365 newsrv->trackit = NULL;
7366 }
7367 next_srv:
7368 newsrv = newsrv->next;
7369 }
7370
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007371 /* We have to initialize the server lookup mechanism depending
7372 * on what LB algorithm was choosen.
7373 */
7374
7375 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7376 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7377 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007378 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7379 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7380 init_server_map(curproxy);
7381 } else {
7382 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7383 fwrr_init_server_groups(curproxy);
7384 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007385 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007386
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007387 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007388 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7389 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7390 fwlc_init_server_tree(curproxy);
7391 } else {
7392 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7393 fas_init_server_tree(curproxy);
7394 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007395 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007396
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007397 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007398 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7399 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7400 chash_init_server_tree(curproxy);
7401 } else {
7402 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7403 init_server_map(curproxy);
7404 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007405 break;
7406 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007407
7408 if (curproxy->options & PR_O_LOGASAP)
7409 curproxy->to_log &= ~LW_BYTES;
7410
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007411 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007412 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007413 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7414 proxy_type_str(curproxy), curproxy->id);
7415 err_code |= ERR_WARN;
7416 }
7417
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007418 if (curproxy->mode != PR_MODE_HTTP) {
7419 int optnum;
7420
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007421 if (curproxy->uri_auth) {
7422 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7423 proxy_type_str(curproxy), curproxy->id);
7424 err_code |= ERR_WARN;
7425 curproxy->uri_auth = NULL;
7426 }
7427
Willy Tarreau87cf5142011-08-19 22:57:24 +02007428 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007429 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7430 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7431 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007432 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007433 }
7434
7435 if (curproxy->options & PR_O_ORGTO) {
7436 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7437 "originalto", proxy_type_str(curproxy), curproxy->id);
7438 err_code |= ERR_WARN;
7439 curproxy->options &= ~PR_O_ORGTO;
7440 }
7441
7442 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7443 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7444 (curproxy->cap & cfg_opts[optnum].cap) &&
7445 (curproxy->options & cfg_opts[optnum].val)) {
7446 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7447 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7448 err_code |= ERR_WARN;
7449 curproxy->options &= ~cfg_opts[optnum].val;
7450 }
7451 }
7452
7453 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7454 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7455 (curproxy->cap & cfg_opts2[optnum].cap) &&
7456 (curproxy->options2 & cfg_opts2[optnum].val)) {
7457 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7458 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7459 err_code |= ERR_WARN;
7460 curproxy->options2 &= ~cfg_opts2[optnum].val;
7461 }
7462 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007463
Pieter Baauwd551fb52013-05-08 22:49:23 +02007464#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007465 if (curproxy->conn_src.bind_hdr_occ) {
7466 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007467 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007468 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007469 err_code |= ERR_WARN;
7470 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007471#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007472 }
7473
Willy Tarreaubaaee002006-06-26 02:48:02 +02007474 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007475 * ensure that we're not cross-dressing a TCP server into HTTP.
7476 */
7477 newsrv = curproxy->srv;
7478 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007479 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007480 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7481 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007482 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007483 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007484
Willy Tarreau0cec3312011-10-31 13:49:26 +01007485 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7486 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7487 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7488 err_code |= ERR_WARN;
7489 }
7490
Willy Tarreauc93cd162014-05-13 15:54:22 +02007491 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007492 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7493 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7494 err_code |= ERR_WARN;
7495 }
7496
Pieter Baauwd551fb52013-05-08 22:49:23 +02007497#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007498 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7499 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007500 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 +01007501 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007502 err_code |= ERR_WARN;
7503 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007504#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007505 newsrv = newsrv->next;
7506 }
7507
Willy Tarreaue42bd962014-09-16 16:21:19 +02007508 /* check if we have a frontend with "tcp-request content" looking at L7
7509 * with no inspect-delay
7510 */
7511 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7512 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7513 if (trule->action == TCP_ACT_CAPTURE &&
7514 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7515 break;
7516 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7517 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7518 break;
7519 }
7520
7521 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7522 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7523 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7524 " This means that these rules will randomly find their contents. This can be fixed by"
7525 " setting the tcp-request inspect-delay.\n",
7526 proxy_type_str(curproxy), curproxy->id);
7527 err_code |= ERR_WARN;
7528 }
7529 }
7530
Willy Tarreauc1a21672009-08-16 22:37:44 +02007531 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007532 if (!curproxy->accept)
7533 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007534
Willy Tarreauc1a21672009-08-16 22:37:44 +02007535 if (curproxy->tcp_req.inspect_delay ||
7536 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007537 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007538
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007539 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007540 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007541 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007542 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007543
7544 /* both TCP and HTTP must check switching rules */
7545 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7546 }
7547
7548 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007549 if (curproxy->tcp_req.inspect_delay ||
7550 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7551 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7552
Emeric Brun97679e72010-09-23 17:56:44 +02007553 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7554 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7555
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007556 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007557 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007558 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007559 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007560
7561 /* If the backend does requires RDP cookie persistence, we have to
7562 * enable the corresponding analyser.
7563 */
7564 if (curproxy->options2 & PR_O2_RDPC_PRST)
7565 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7566 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007567 }
7568
7569 /***********************************************************/
7570 /* At this point, target names have already been resolved. */
7571 /***********************************************************/
7572
7573 /* Check multi-process mode compatibility */
7574
7575 if (global.nbproc > 1 && global.stats_fe) {
7576 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7577 unsigned long mask;
7578
7579 mask = nbits(global.nbproc);
7580 if (global.stats_fe->bind_proc)
7581 mask &= global.stats_fe->bind_proc;
7582
7583 if (bind_conf->bind_proc)
7584 mask &= bind_conf->bind_proc;
7585
7586 /* stop here if more than one process is used */
7587 if (popcount(mask) > 1)
7588 break;
7589 }
7590 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7591 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");
7592 }
7593 }
7594
7595 /* Make each frontend inherit bind-process from its listeners when not specified. */
7596 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7597 if (curproxy->bind_proc)
7598 continue;
7599
7600 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7601 unsigned long mask;
7602
7603 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7604 curproxy->bind_proc |= mask;
7605 }
7606
7607 if (!curproxy->bind_proc)
7608 curproxy->bind_proc = ~0UL;
7609 }
7610
7611 if (global.stats_fe) {
7612 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7613 unsigned long mask;
7614
7615 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7616 global.stats_fe->bind_proc |= mask;
7617 }
7618 if (!global.stats_fe->bind_proc)
7619 global.stats_fe->bind_proc = ~0UL;
7620 }
7621
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007622 /* propagate bindings from frontends to backends. Don't do it if there
7623 * are any fatal errors as we must not call it with unresolved proxies.
7624 */
7625 if (!cfgerr) {
7626 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7627 if (curproxy->cap & PR_CAP_FE)
7628 propagate_processes(curproxy, NULL);
7629 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007630 }
7631
7632 /* Bind each unbound backend to all processes when not specified. */
7633 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7634 if (curproxy->bind_proc)
7635 continue;
7636 curproxy->bind_proc = ~0UL;
7637 }
7638
7639 /*******************************************************/
7640 /* At this step, all proxies have a non-null bind_proc */
7641 /*******************************************************/
7642
7643 /* perform the final checks before creating tasks */
7644
7645 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7646 struct listener *listener;
7647 unsigned int next_id;
7648 int nbproc;
7649
7650 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007651
Emeric Brunc52962f2012-11-15 18:28:02 +01007652#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007653 /* Configure SSL for each bind line.
7654 * Note: if configuration fails at some point, the ->ctx member
7655 * remains NULL so that listeners can later detach.
7656 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007657 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007658 int alloc_ctx;
7659
Emeric Brunc52962f2012-11-15 18:28:02 +01007660 if (!bind_conf->is_ssl) {
7661 if (bind_conf->default_ctx) {
7662 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7663 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7664 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007665 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007666 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007667 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007668 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007669 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007670 cfgerr++;
7671 continue;
7672 }
7673
Emeric Brun8dc60392014-05-09 13:52:00 +02007674 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007675 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007676 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7677 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");
7678 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007679 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007680 cfgerr++;
7681 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007682 }
7683
Emeric Brunfc0421f2012-09-07 17:30:07 +02007684 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007685 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007686 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007687#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007688
Willy Tarreaue6b98942007-10-29 01:09:36 +01007689 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007690 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007691 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007692 if (!listener->luid) {
7693 /* listener ID not set, use automatic numbering with first
7694 * spare entry starting with next_luid.
7695 */
7696 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7697 listener->conf.id.key = listener->luid = next_id;
7698 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007699 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007700 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007701
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007702 /* enable separate counters */
7703 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7704 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007705 if (!listener->name)
7706 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007707 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007708
Willy Tarreaue6b98942007-10-29 01:09:36 +01007709 if (curproxy->options & PR_O_TCP_NOLING)
7710 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007711 if (!listener->maxconn)
7712 listener->maxconn = curproxy->maxconn;
7713 if (!listener->backlog)
7714 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007715 if (!listener->maxaccept)
7716 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7717
7718 /* we want to have an optimal behaviour on single process mode to
7719 * maximize the work at once, but in multi-process we want to keep
7720 * some fairness between processes, so we target half of the max
7721 * number of events to be balanced over all the processes the proxy
7722 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7723 * used to disable the limit.
7724 */
7725 if (listener->maxaccept > 0) {
7726 if (nbproc > 1)
7727 listener->maxaccept = (listener->maxaccept + 1) / 2;
7728 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7729 }
7730
Willy Tarreau9903f0e2015-04-04 18:50:31 +02007731 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02007732 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007733 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01007734 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007735
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007736 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7737 listener->options |= LI_O_TCP_RULES;
7738
Willy Tarreaude3041d2010-05-31 10:56:17 +02007739 if (curproxy->mon_mask.s_addr)
7740 listener->options |= LI_O_CHK_MONNET;
7741
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007742 /* smart accept mode is automatic in HTTP mode */
7743 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007744 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007745 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7746 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007747 }
7748
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007749 /* Release unused SSL configs */
7750 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7751 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007752 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007753#ifdef USE_OPENSSL
7754 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007755 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007756 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007757 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007758 free(bind_conf->crl_file);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007759 free(bind_conf->tls_ticket_keys);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007760#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007761 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007762
Willy Tarreau102df612014-05-07 23:56:38 +02007763 if (nbproc > 1) {
7764 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02007765 int count, maxproc = 0;
7766
7767 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7768 count = popcount(bind_conf->bind_proc);
7769 if (count > maxproc)
7770 maxproc = count;
7771 }
7772 /* backends have 0, frontends have 1 or more */
7773 if (maxproc != 1)
7774 Warning("Proxy '%s': in multi-process mode, stats will be"
7775 " limited to process assigned to the current request.\n",
7776 curproxy->id);
7777
Willy Tarreau102df612014-05-07 23:56:38 +02007778 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7779 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7780 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007781 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007782 }
Willy Tarreau102df612014-05-07 23:56:38 +02007783 if (curproxy->appsession_name) {
7784 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7785 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007786 }
Willy Tarreau102df612014-05-07 23:56:38 +02007787 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7788 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7789 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007790 }
7791 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007792
7793 /* create the task associated with the proxy */
7794 curproxy->task = task_new();
7795 if (curproxy->task) {
7796 curproxy->task->context = curproxy;
7797 curproxy->task->process = manage_proxy;
7798 /* no need to queue, it will be done automatically if some
7799 * listener gets limited.
7800 */
7801 curproxy->task->expire = TICK_ETERNITY;
7802 } else {
7803 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7804 curproxy->id);
7805 cfgerr++;
7806 }
Willy Tarreaub369a042014-09-16 13:21:03 +02007807 }
7808
Willy Tarreaufbb78422011-06-05 15:38:35 +02007809 /* automatically compute fullconn if not set. We must not do it in the
7810 * loop above because cross-references are not yet fully resolved.
7811 */
7812 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7813 /* If <fullconn> is not set, let's set it to 10% of the sum of
7814 * the possible incoming frontend's maxconns.
7815 */
7816 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7817 struct proxy *fe;
7818 int total = 0;
7819
7820 /* sum up the number of maxconns of frontends which
7821 * reference this backend at least once or which are
7822 * the same one ('listen').
7823 */
7824 for (fe = proxy; fe; fe = fe->next) {
7825 struct switching_rule *rule;
7826 struct hdr_exp *exp;
7827 int found = 0;
7828
7829 if (!(fe->cap & PR_CAP_FE))
7830 continue;
7831
7832 if (fe == curproxy) /* we're on a "listen" instance */
7833 found = 1;
7834
7835 if (fe->defbe.be == curproxy) /* "default_backend" */
7836 found = 1;
7837
7838 /* check if a "use_backend" rule matches */
7839 if (!found) {
7840 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007841 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007842 found = 1;
7843 break;
7844 }
7845 }
7846 }
7847
7848 /* check if a "reqsetbe" rule matches */
7849 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7850 if (exp->action == ACT_SETBE &&
7851 (struct proxy *)exp->replace == curproxy) {
7852 found = 1;
7853 break;
7854 }
7855 }
7856
7857 /* now we've checked all possible ways to reference a backend
7858 * from a frontend.
7859 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007860 if (!found)
7861 continue;
7862 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007863 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007864 /* we have the sum of the maxconns in <total>. We only
7865 * keep 10% of that sum to set the default fullconn, with
7866 * a hard minimum of 1 (to avoid a divide by zero).
7867 */
7868 curproxy->fullconn = (total + 9) / 10;
7869 if (!curproxy->fullconn)
7870 curproxy->fullconn = 1;
7871 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007872 }
7873
Willy Tarreau056f5682010-06-06 15:51:11 +02007874 /* initialize stick-tables on backend capable proxies. This must not
7875 * be done earlier because the data size may be discovered while parsing
7876 * other proxies.
7877 */
Godbach9703e662013-12-11 21:11:41 +08007878 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007879 if (curproxy->state == PR_STSTOPPED)
7880 continue;
7881
Godbach9703e662013-12-11 21:11:41 +08007882 if (!stktable_init(&curproxy->table)) {
7883 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7884 cfgerr++;
7885 }
7886 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007887
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007888 /*
7889 * Recount currently required checks.
7890 */
7891
7892 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7893 int optnum;
7894
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007895 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7896 if (curproxy->options & cfg_opts[optnum].val)
7897 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007898
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007899 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7900 if (curproxy->options2 & cfg_opts2[optnum].val)
7901 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007902 }
7903
Willy Tarreau122541c2011-09-07 21:24:49 +02007904 if (peers) {
7905 struct peers *curpeers = peers, **last;
7906 struct peer *p, *pb;
7907
7908 /* Remove all peers sections which don't have a valid listener.
7909 * This can happen when a peers section is never referenced and
7910 * does not contain a local peer.
7911 */
7912 last = &peers;
7913 while (*last) {
7914 curpeers = *last;
7915 if (curpeers->peers_fe) {
7916 last = &curpeers->next;
7917 continue;
7918 }
7919
7920 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7921 curpeers->id, localpeer);
7922
7923 p = curpeers->remote;
7924 while (p) {
7925 pb = p->next;
7926 free(p->id);
7927 free(p);
7928 p = pb;
7929 }
7930
7931 /* Destroy and unlink this curpeers section.
7932 * Note: curpeers is backed up into *last.
7933 */
7934 free(curpeers->id);
7935 curpeers = curpeers->next;
7936 free(*last);
7937 *last = curpeers;
7938 }
7939 }
7940
Simon Horman0d16a402015-01-30 11:22:58 +09007941 if (mailers) {
7942 struct mailers *curmailers = mailers, **last;
7943 struct mailer *m, *mb;
7944
7945 /* Remove all mailers sections which don't have a valid listener.
7946 * This can happen when a mailers section is never referenced.
7947 */
7948 last = &mailers;
7949 while (*last) {
7950 curmailers = *last;
7951 if (curmailers->users) {
7952 last = &curmailers->next;
7953 continue;
7954 }
7955
7956 Warning("Removing incomplete section 'mailers %s'.\n",
7957 curmailers->id);
7958
7959 m = curmailers->mailer_list;
7960 while (m) {
7961 mb = m->next;
7962 free(m->id);
7963 free(m);
7964 m = mb;
7965 }
7966
7967 /* Destroy and unlink this curmailers section.
7968 * Note: curmailers is backed up into *last.
7969 */
7970 free(curmailers->id);
7971 curmailers = curmailers->next;
7972 free(*last);
7973 *last = curmailers;
7974 }
7975 }
7976
Willy Tarreau34eb6712011-10-24 18:15:04 +02007977 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007978 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007979 MEM_F_SHARED);
7980
Willy Tarreaubb925012009-07-23 13:36:36 +02007981 if (cfgerr > 0)
7982 err_code |= ERR_ALERT | ERR_FATAL;
7983 out:
7984 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007985}
7986
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007987/*
7988 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7989 * parsing sessions.
7990 */
7991void cfg_register_keywords(struct cfg_kw_list *kwl)
7992{
7993 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7994}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007995
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007996/*
7997 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7998 */
7999void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8000{
8001 LIST_DEL(&kwl->list);
8002 LIST_INIT(&kwl->list);
8003}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008004
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008005/* this function register new section in the haproxy configuration file.
8006 * <section_name> is the name of this new section and <section_parser>
8007 * is the called parser. If two section declaration have the same name,
8008 * only the first declared is used.
8009 */
8010int cfg_register_section(char *section_name,
8011 int (*section_parser)(const char *, int, char **, int))
8012{
8013 struct cfg_section *cs;
8014
8015 cs = calloc(1, sizeof(*cs));
8016 if (!cs) {
8017 Alert("register section '%s': out of memory.\n", section_name);
8018 return 0;
8019 }
8020
8021 cs->section_name = section_name;
8022 cs->section_parser = section_parser;
8023
8024 LIST_ADDQ(&sections, &cs->list);
8025
8026 return 1;
8027}
8028
Willy Tarreaubaaee002006-06-26 02:48:02 +02008029/*
8030 * Local variables:
8031 * c-indent-level: 8
8032 * c-basic-offset: 8
8033 * End:
8034 */