blob: cf6637be89e767bbbe149f1d2219b6b73bd82109 [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]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001797 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001798 }
1799 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001800 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001801 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001802 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001803
1804 if (!*args[2]) {
1805 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1806 file, linenum, args[0]);
1807 err_code |= ERR_ALERT | ERR_FATAL;
1808 goto out;
1809 }
1810
1811 err = invalid_char(args[1]);
1812 if (err) {
1813 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1814 file, linenum, *err, args[1]);
1815 err_code |= ERR_ALERT | ERR_FATAL;
1816 goto out;
1817 }
1818
1819 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1820 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1821 err_code |= ERR_ALERT | ERR_ABORT;
1822 goto out;
1823 }
1824
1825 /* the peers are linked backwards first */
1826 curpeers->count++;
1827 newpeer->next = curpeers->remote;
1828 curpeers->remote = newpeer;
1829 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001830 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001831 newpeer->conf.line = linenum;
1832
1833 newpeer->last_change = now.tv_sec;
1834 newpeer->id = strdup(args[1]);
1835
Willy Tarreau902636f2013-03-10 19:44:48 +01001836 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001837 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001838 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001839 err_code |= ERR_ALERT | ERR_FATAL;
1840 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001841 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001842
1843 proto = protocol_by_family(sk->ss_family);
1844 if (!proto || !proto->connect) {
1845 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1846 file, linenum, args[0], args[1]);
1847 err_code |= ERR_ALERT | ERR_FATAL;
1848 goto out;
1849 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001850
1851 if (port1 != port2) {
1852 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1853 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001854 err_code |= ERR_ALERT | ERR_FATAL;
1855 goto out;
1856 }
1857
Willy Tarreau2aa38802013-02-20 19:20:59 +01001858 if (!port1) {
1859 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1860 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001861 err_code |= ERR_ALERT | ERR_FATAL;
1862 goto out;
1863 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001864
Emeric Brun32da3c42010-09-23 18:39:19 +02001865 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001866 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001867 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001868 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001869
Emeric Brun32da3c42010-09-23 18:39:19 +02001870 if (strcmp(newpeer->id, localpeer) == 0) {
1871 /* Current is local peer, it define a frontend */
1872 newpeer->local = 1;
1873
1874 if (!curpeers->peers_fe) {
1875 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1876 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1877 err_code |= ERR_ALERT | ERR_ABORT;
1878 goto out;
1879 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001880
Willy Tarreau237250c2011-07-29 01:49:03 +02001881 init_new_proxy(curpeers->peers_fe);
1882 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001883 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001884 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1885 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01001886 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02001887
1888 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1889
Willy Tarreau902636f2013-03-10 19:44:48 +01001890 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1891 if (errmsg && *errmsg) {
1892 indent_msg(&errmsg, 2);
1893 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001894 }
1895 else
1896 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1897 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001898 err_code |= ERR_FATAL;
1899 goto out;
1900 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001901
1902 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001903 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001904 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1905 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02001906 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02001907 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001908 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01001909 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001910 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1911 global.maxsock += l->maxconn;
1912 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001913 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001914 else {
1915 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1916 file, linenum, args[0], args[1],
1917 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1918 err_code |= ERR_FATAL;
1919 goto out;
1920 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001921 }
1922 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001923 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
1924 curpeers->state = PR_STSTOPPED;
1925 }
1926 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
1927 curpeers->state = PR_STNEW;
1928 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001929 else if (*args[0] != 0) {
1930 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1931 err_code |= ERR_ALERT | ERR_FATAL;
1932 goto out;
1933 }
1934
1935out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001936 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001937 return err_code;
1938}
1939
Simon Horman0d16a402015-01-30 11:22:58 +09001940
1941/*
1942 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
1943 * Returns the error code, 0 if OK, or any combination of :
1944 * - ERR_ABORT: must abort ASAP
1945 * - ERR_FATAL: we can continue parsing but not start the service
1946 * - ERR_WARN: a warning has been emitted
1947 * - ERR_ALERT: an alert has been emitted
1948 * Only the two first ones can stop processing, the two others are just
1949 * indicators.
1950 */
1951int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
1952{
1953 static struct mailers *curmailers = NULL;
1954 struct mailer *newmailer = NULL;
1955 const char *err;
1956 int err_code = 0;
1957 char *errmsg = NULL;
1958
1959 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
1960 if (!*args[1]) {
1961 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
1962 err_code |= ERR_ALERT | ERR_ABORT;
1963 goto out;
1964 }
1965
1966 err = invalid_char(args[1]);
1967 if (err) {
1968 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1969 file, linenum, *err, args[0], args[1]);
1970 err_code |= ERR_ALERT | ERR_ABORT;
1971 goto out;
1972 }
1973
1974 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
1975 /*
1976 * If there are two proxies with the same name only following
1977 * combinations are allowed:
1978 */
1979 if (strcmp(curmailers->id, args[1]) == 0) {
1980 Warning("Parsing [%s:%d]: mailers '%s' has same name as another mailers (declared at %s:%d).\n",
1981 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
1982 err_code |= ERR_WARN;
1983 }
1984 }
1985
1986 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
1987 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1988 err_code |= ERR_ALERT | ERR_ABORT;
1989 goto out;
1990 }
1991
1992 curmailers->next = mailers;
1993 mailers = curmailers;
1994 curmailers->conf.file = strdup(file);
1995 curmailers->conf.line = linenum;
1996 curmailers->id = strdup(args[1]);
1997 }
1998 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
1999 struct sockaddr_storage *sk;
2000 int port1, port2;
2001 struct protocol *proto;
2002
2003 if (!*args[2]) {
2004 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2005 file, linenum, args[0]);
2006 err_code |= ERR_ALERT | ERR_FATAL;
2007 goto out;
2008 }
2009
2010 err = invalid_char(args[1]);
2011 if (err) {
2012 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2013 file, linenum, *err, args[1]);
2014 err_code |= ERR_ALERT | ERR_FATAL;
2015 goto out;
2016 }
2017
2018 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2019 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2020 err_code |= ERR_ALERT | ERR_ABORT;
2021 goto out;
2022 }
2023
2024 /* the mailers are linked backwards first */
2025 curmailers->count++;
2026 newmailer->next = curmailers->mailer_list;
2027 curmailers->mailer_list = newmailer;
2028 newmailer->mailers = curmailers;
2029 newmailer->conf.file = strdup(file);
2030 newmailer->conf.line = linenum;
2031
2032 newmailer->id = strdup(args[1]);
2033
2034 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2035 if (!sk) {
2036 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2037 err_code |= ERR_ALERT | ERR_FATAL;
2038 goto out;
2039 }
2040
2041 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002042 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2043 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002044 file, linenum, args[0], args[1]);
2045 err_code |= ERR_ALERT | ERR_FATAL;
2046 goto out;
2047 }
2048
2049 if (port1 != port2) {
2050 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed 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 if (!port1) {
2057 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2058 file, linenum, args[0], args[1], args[2]);
2059 err_code |= ERR_ALERT | ERR_FATAL;
2060 goto out;
2061 }
2062
2063 newmailer->addr = *sk;
2064 newmailer->proto = proto;
2065 newmailer->xprt = &raw_sock;
2066 newmailer->sock_init_arg = NULL;
2067 } /* neither "mailer" nor "mailers" */
2068 else if (*args[0] != 0) {
2069 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2070 err_code |= ERR_ALERT | ERR_FATAL;
2071 goto out;
2072 }
2073
2074out:
2075 free(errmsg);
2076 return err_code;
2077}
2078
Simon Horman9dc49962015-01-30 11:22:59 +09002079static void free_email_alert(struct proxy *p)
2080{
2081 free(p->email_alert.mailers.name);
2082 p->email_alert.mailers.name = NULL;
2083 free(p->email_alert.from);
2084 p->email_alert.from = NULL;
2085 free(p->email_alert.to);
2086 p->email_alert.to = NULL;
2087 free(p->email_alert.myhostname);
2088 p->email_alert.myhostname = NULL;
2089}
2090
Willy Tarreau3842f002009-06-14 11:39:52 +02002091int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002092{
2093 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002094 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002095 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002096 int rc;
2097 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002098 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002099 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002100 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002101 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002102 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103
Willy Tarreau977b8e42006-12-29 14:19:17 +01002104 if (!strcmp(args[0], "listen"))
2105 rc = PR_CAP_LISTEN;
2106 else if (!strcmp(args[0], "frontend"))
2107 rc = PR_CAP_FE | PR_CAP_RS;
2108 else if (!strcmp(args[0], "backend"))
2109 rc = PR_CAP_BE | PR_CAP_RS;
2110 else if (!strcmp(args[0], "ruleset"))
2111 rc = PR_CAP_RS;
2112 else
2113 rc = PR_CAP_NONE;
2114
2115 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002116 struct ebpt_node *node;
2117
Willy Tarreaubaaee002006-06-26 02:48:02 +02002118 if (!*args[1]) {
2119 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2120 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2121 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002122 err_code |= ERR_ALERT | ERR_ABORT;
2123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002124 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002125
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002126 err = invalid_char(args[1]);
2127 if (err) {
2128 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2129 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002130 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002131 }
2132
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002133 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
2134 curproxy = container_of(node, struct proxy, conf.by_name);
2135
2136 if (strcmp(curproxy->id, args[1]) != 0)
2137 break;
2138
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002139 /*
2140 * If there are two proxies with the same name only following
2141 * combinations are allowed:
2142 *
2143 * listen backend frontend ruleset
2144 * listen - - - -
2145 * backend - - OK -
2146 * frontend - OK - -
2147 * ruleset - - - -
2148 */
2149
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002150 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
2151 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02002152 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
2153 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2154 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02002155 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002156 }
2157 }
2158
Willy Tarreaubaaee002006-06-26 02:48:02 +02002159 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2160 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002161 err_code |= ERR_ALERT | ERR_ABORT;
2162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002163 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002164
Willy Tarreau97cb7802010-01-03 20:23:58 +01002165 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002166 curproxy->next = proxy;
2167 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002168 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2169 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002170 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002171 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002172 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002173 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002174
2175 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002176 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002177 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02002178
Willy Tarreau4348fad2012-09-20 16:48:07 +02002179 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2180
Willy Tarreau902636f2013-03-10 19:44:48 +01002181 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2182 if (errmsg && *errmsg) {
2183 indent_msg(&errmsg, 2);
2184 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002185 }
2186 else
2187 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2188 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002189 err_code |= ERR_FATAL;
2190 goto out;
2191 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002192
Willy Tarreau4348fad2012-09-20 16:48:07 +02002193 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002194 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002196 }
2197
2198 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002199 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002200 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002201
Willy Tarreaubaaee002006-06-26 02:48:02 +02002202 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002204 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002205 curproxy->no_options = defproxy.no_options;
2206 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002207 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002208 curproxy->except_net = defproxy.except_net;
2209 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002210 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002211 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002212
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002213 if (defproxy.fwdfor_hdr_len) {
2214 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2215 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2216 }
2217
Willy Tarreaub86db342009-11-30 11:50:16 +01002218 if (defproxy.orgto_hdr_len) {
2219 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2220 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2221 }
2222
Mark Lamourinec2247f02012-01-04 13:02:01 -05002223 if (defproxy.server_id_hdr_len) {
2224 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2225 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2226 }
2227
Willy Tarreau977b8e42006-12-29 14:19:17 +01002228 if (curproxy->cap & PR_CAP_FE) {
2229 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002230 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002231 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002232
2233 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002234 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2235 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002236
2237 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2238 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002239
Willy Tarreau977b8e42006-12-29 14:19:17 +01002240 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002241 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002242 curproxy->fullconn = defproxy.fullconn;
2243 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002244 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002246 if (defproxy.check_req) {
2247 curproxy->check_req = calloc(1, defproxy.check_len);
2248 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2249 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002250 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002252 if (defproxy.expect_str) {
2253 curproxy->expect_str = strdup(defproxy.expect_str);
2254 if (defproxy.expect_regex) {
2255 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002256 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2257 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002258 }
2259 }
2260
Willy Tarreau67402132012-05-31 20:40:20 +02002261 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002262 if (defproxy.cookie_name)
2263 curproxy->cookie_name = strdup(defproxy.cookie_name);
2264 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002265 if (defproxy.cookie_domain)
2266 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002267
Willy Tarreau31936852010-10-06 16:59:56 +02002268 if (defproxy.cookie_maxidle)
2269 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2270
2271 if (defproxy.cookie_maxlife)
2272 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2273
Emeric Brun647caf12009-06-30 17:57:00 +02002274 if (defproxy.rdp_cookie_name)
2275 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2276 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2277
Willy Tarreau01732802007-11-01 22:48:15 +01002278 if (defproxy.url_param_name)
2279 curproxy->url_param_name = strdup(defproxy.url_param_name);
2280 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002281
Benoitaffb4812009-03-25 13:02:10 +01002282 if (defproxy.hh_name)
2283 curproxy->hh_name = strdup(defproxy.hh_name);
2284 curproxy->hh_len = defproxy.hh_len;
2285 curproxy->hh_match_domain = defproxy.hh_match_domain;
2286
Willy Tarreauef9a3602012-12-08 22:29:20 +01002287 if (defproxy.conn_src.iface_name)
2288 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2289 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002290 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002291#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002292 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002293#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002294 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002296 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002297 if (defproxy.capture_name)
2298 curproxy->capture_name = strdup(defproxy.capture_name);
2299 curproxy->capture_namelen = defproxy.capture_namelen;
2300 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002302
Willy Tarreau977b8e42006-12-29 14:19:17 +01002303 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002304 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002305 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002306 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002307 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002308 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002309 curproxy->mon_net = defproxy.mon_net;
2310 curproxy->mon_mask = defproxy.mon_mask;
2311 if (defproxy.monitor_uri)
2312 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2313 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002314 if (defproxy.defbe.name)
2315 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002316
2317 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002318 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2319 if (curproxy->conf.logformat_string &&
2320 curproxy->conf.logformat_string != default_http_log_format &&
2321 curproxy->conf.logformat_string != default_tcp_log_format &&
2322 curproxy->conf.logformat_string != clf_http_log_format)
2323 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2324
2325 if (defproxy.conf.lfs_file) {
2326 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2327 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2328 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002329 }
2330
2331 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002332 curproxy->timeout.connect = defproxy.timeout.connect;
2333 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002334 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002335 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002336 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002337 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002338 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002339 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002340 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002341 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002342 }
2343
Willy Tarreaubaaee002006-06-26 02:48:02 +02002344 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002345 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002346
2347 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002348 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002349 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002350 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002351 LIST_INIT(&node->list);
2352 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2353 }
2354
Willy Tarreau62a61232013-04-12 18:13:46 +02002355 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2356 if (curproxy->conf.uniqueid_format_string)
2357 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2358
Willy Tarreau094af4e2015-01-07 15:03:42 +01002359 if (defproxy.log_tag)
2360 curproxy->log_tag = strdup(defproxy.log_tag);
2361
Willy Tarreau62a61232013-04-12 18:13:46 +02002362 if (defproxy.conf.uif_file) {
2363 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2364 curproxy->conf.uif_line = defproxy.conf.uif_line;
2365 }
William Lallemanda73203e2012-03-12 12:48:57 +01002366
2367 /* copy default header unique id */
2368 if (defproxy.header_unique_id)
2369 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2370
William Lallemand82fe75c2012-10-23 10:25:10 +02002371 /* default compression options */
2372 if (defproxy.comp != NULL) {
2373 curproxy->comp = calloc(1, sizeof(struct comp));
2374 curproxy->comp->algos = defproxy.comp->algos;
2375 curproxy->comp->types = defproxy.comp->types;
2376 }
2377
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002379 curproxy->conf.used_listener_id = EB_ROOT;
2380 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002381
Simon Horman98637e52014-06-20 12:30:16 +09002382 if (defproxy.check_path)
2383 curproxy->check_path = strdup(defproxy.check_path);
2384 if (defproxy.check_command)
2385 curproxy->check_command = strdup(defproxy.check_command);
2386
Simon Horman9dc49962015-01-30 11:22:59 +09002387 if (defproxy.email_alert.mailers.name)
2388 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2389 if (defproxy.email_alert.from)
2390 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2391 if (defproxy.email_alert.to)
2392 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2393 if (defproxy.email_alert.myhostname)
2394 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002395 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002396
Willy Tarreau93893792009-07-23 13:19:11 +02002397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398 }
2399 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2400 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002401 /* FIXME-20070101: we should do this too at the end of the
2402 * config parsing to free all default values.
2403 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002404 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002405 free(defproxy.check_command);
2406 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002407 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002408 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002409 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002410 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002411 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002412 free(defproxy.capture_name);
2413 free(defproxy.monitor_uri);
2414 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002415 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002416 free(defproxy.fwdfor_hdr_name);
2417 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002418 free(defproxy.orgto_hdr_name);
2419 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002420 free(defproxy.server_id_hdr_name);
2421 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002422 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002423 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002424 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002425 free(defproxy.expect_regex);
2426 defproxy.expect_regex = NULL;
2427 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002428
Willy Tarreau62a61232013-04-12 18:13:46 +02002429 if (defproxy.conf.logformat_string != default_http_log_format &&
2430 defproxy.conf.logformat_string != default_tcp_log_format &&
2431 defproxy.conf.logformat_string != clf_http_log_format)
2432 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002433
Willy Tarreau62a61232013-04-12 18:13:46 +02002434 free(defproxy.conf.uniqueid_format_string);
2435 free(defproxy.conf.lfs_file);
2436 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002437 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002438 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002439
Willy Tarreaua534fea2008-08-03 12:19:50 +02002440 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002441 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002442
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443 /* we cannot free uri_auth because it might already be used */
2444 init_default_instance();
2445 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002446 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2447 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002448 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 }
2451 else if (curproxy == NULL) {
2452 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002455 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002456
2457 /* update the current file and line being parsed */
2458 curproxy->conf.args.file = curproxy->conf.file;
2459 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002460
2461 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002462 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2463 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2464 if (err_code & ERR_FATAL)
2465 goto out;
2466 }
2467 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002468 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002469 int cur_arg;
2470
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471 if (curproxy == &defproxy) {
2472 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002473 err_code |= ERR_ALERT | ERR_FATAL;
2474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002476 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002477 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478
Willy Tarreau24709282013-03-10 21:32:12 +01002479 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002480 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002481 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002482 err_code |= ERR_ALERT | ERR_FATAL;
2483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002484 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002485
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002486 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002487
2488 /* use default settings for unix sockets */
2489 bind_conf->ux.uid = global.unix_bind.ux.uid;
2490 bind_conf->ux.gid = global.unix_bind.ux.gid;
2491 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002492
2493 /* NOTE: the following line might create several listeners if there
2494 * are comma-separated IPs or port ranges. So all further processing
2495 * will have to be applied to all listeners created after last_listen.
2496 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002497 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2498 if (errmsg && *errmsg) {
2499 indent_msg(&errmsg, 2);
2500 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002501 }
2502 else
2503 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2504 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002505 err_code |= ERR_ALERT | ERR_FATAL;
2506 goto out;
2507 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002508
Willy Tarreau4348fad2012-09-20 16:48:07 +02002509 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2510 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002511 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002512 }
2513
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002514 cur_arg = 2;
2515 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002516 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002517 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002518 char *err;
2519
Willy Tarreau26982662012-09-12 23:17:10 +02002520 kw = bind_find_kw(args[cur_arg]);
2521 if (kw) {
2522 char *err = NULL;
2523 int code;
2524
2525 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002526 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2527 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002528 cur_arg += 1 + kw->skip ;
2529 err_code |= ERR_ALERT | ERR_FATAL;
2530 goto out;
2531 }
2532
Willy Tarreau4348fad2012-09-20 16:48:07 +02002533 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002534 err_code |= code;
2535
2536 if (code) {
2537 if (err && *err) {
2538 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002539 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002540 }
2541 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002542 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2543 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002544 if (code & ERR_FATAL) {
2545 free(err);
2546 cur_arg += 1 + kw->skip;
2547 goto out;
2548 }
2549 }
2550 free(err);
2551 cur_arg += 1 + kw->skip;
2552 continue;
2553 }
2554
Willy Tarreau8638f482012-09-18 18:01:17 +02002555 err = NULL;
2556 if (!bind_dumped) {
2557 bind_dump_kws(&err);
2558 indent_msg(&err, 4);
2559 bind_dumped = 1;
2560 }
2561
2562 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2563 file, linenum, args[0], args[1], args[cur_arg],
2564 err ? " Registered keywords :" : "", err ? err : "");
2565 free(err);
2566
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002569 }
Willy Tarreau93893792009-07-23 13:19:11 +02002570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 }
2572 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002573 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2575 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002576 err_code |= ERR_ALERT | ERR_FATAL;
2577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002579 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002580 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002581
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 /* flush useless bits */
2583 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002586 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002587 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002588 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002589
Willy Tarreau1c47f852006-07-09 08:22:27 +02002590 if (!*args[1]) {
2591 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2592 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002593 err_code |= ERR_ALERT | ERR_FATAL;
2594 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002595 }
2596
Willy Tarreaua534fea2008-08-03 12:19:50 +02002597 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002598 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002599 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002600 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002601 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2602
Willy Tarreau93893792009-07-23 13:19:11 +02002603 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002604 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2606 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2607 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2608 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2609 else {
2610 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002611 err_code |= ERR_ALERT | ERR_FATAL;
2612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002613 }
2614 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002615 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002616 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002617
2618 if (curproxy == &defproxy) {
2619 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\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 if (!*args[1]) {
2626 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2627 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002628 err_code |= ERR_ALERT | ERR_FATAL;
2629 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002630 }
2631
2632 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002633 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002634
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002635 if (curproxy->uuid <= 0) {
2636 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002637 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002638 err_code |= ERR_ALERT | ERR_FATAL;
2639 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002640 }
2641
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002642 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2643 if (node) {
2644 struct proxy *target = container_of(node, struct proxy, conf.id);
2645 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2646 file, linenum, proxy_type_str(curproxy), curproxy->id,
2647 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
2650 }
2651 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002652 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002653 else if (!strcmp(args[0], "description")) {
2654 int i, len=0;
2655 char *d;
2656
Cyril Bonté99ed3272010-01-24 23:29:44 +01002657 if (curproxy == &defproxy) {
2658 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2659 file, linenum, args[0]);
2660 err_code |= ERR_ALERT | ERR_FATAL;
2661 goto out;
2662 }
2663
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002664 if (!*args[1]) {
2665 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2666 file, linenum, args[0]);
2667 return -1;
2668 }
2669
Willy Tarreau348acfe2014-04-14 15:00:39 +02002670 for (i = 1; *args[i]; i++)
2671 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002672
2673 d = (char *)calloc(1, len);
2674 curproxy->desc = d;
2675
Willy Tarreau348acfe2014-04-14 15:00:39 +02002676 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2677 for (i = 2; *args[i]; i++)
2678 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002679
2680 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002681 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2682 curproxy->state = PR_STSTOPPED;
2683 }
2684 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2685 curproxy->state = PR_STNEW;
2686 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002687 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2688 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002689 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002690
2691 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002692 unsigned int low, high;
2693
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002694 if (strcmp(args[cur_arg], "all") == 0) {
2695 set = 0;
2696 break;
2697 }
2698 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002699 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002700 }
2701 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002702 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002703 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002704 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002705 char *dash = strchr(args[cur_arg], '-');
2706
2707 low = high = str2uic(args[cur_arg]);
2708 if (dash)
2709 high = str2uic(dash + 1);
2710
2711 if (high < low) {
2712 unsigned int swap = low;
2713 low = high;
2714 high = swap;
2715 }
2716
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002717 if (low < 1 || high > LONGBITS) {
2718 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2719 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002720 err_code |= ERR_ALERT | ERR_FATAL;
2721 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002722 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002723 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002724 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002725 }
2726 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002727 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2728 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002729 err_code |= ERR_ALERT | ERR_FATAL;
2730 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002731 }
2732 cur_arg++;
2733 }
2734 curproxy->bind_proc = set;
2735 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002736 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002737 if (curproxy == &defproxy) {
2738 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002739 err_code |= ERR_ALERT | ERR_FATAL;
2740 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002741 }
2742
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002743 err = invalid_char(args[1]);
2744 if (err) {
2745 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2746 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002747 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002748 }
2749
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002750 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002751 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2752 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002753 err_code |= ERR_ALERT | ERR_FATAL;
2754 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002755 }
2756 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002757 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2758 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759
Willy Tarreau977b8e42006-12-29 14:19:17 +01002760 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002761 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002762
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 if (*(args[1]) == 0) {
2764 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2765 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002768 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002769
Willy Tarreau67402132012-05-31 20:40:20 +02002770 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002771 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002772 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002773 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002774 curproxy->cookie_name = strdup(args[1]);
2775 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002776
Willy Tarreaubaaee002006-06-26 02:48:02 +02002777 cur_arg = 2;
2778 while (*(args[cur_arg])) {
2779 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002780 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002781 }
2782 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002783 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002784 }
2785 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002786 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002787 }
2788 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002789 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002790 }
2791 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002792 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002793 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002794 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002795 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002796 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002797 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002798 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002799 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002800 else if (!strcmp(args[cur_arg], "httponly")) {
2801 curproxy->ck_opts |= PR_CK_HTTPONLY;
2802 }
2803 else if (!strcmp(args[cur_arg], "secure")) {
2804 curproxy->ck_opts |= PR_CK_SECURE;
2805 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002806 else if (!strcmp(args[cur_arg], "domain")) {
2807 if (!*args[cur_arg + 1]) {
2808 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2809 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002810 err_code |= ERR_ALERT | ERR_FATAL;
2811 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002812 }
2813
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002814 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002815 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002816 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2817 " dots nor does not start with a dot."
2818 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002819 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002820 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002821 }
2822
2823 err = invalid_domainchar(args[cur_arg + 1]);
2824 if (err) {
2825 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2826 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002827 err_code |= ERR_ALERT | ERR_FATAL;
2828 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002829 }
2830
Willy Tarreau68a897b2009-12-03 23:28:34 +01002831 if (!curproxy->cookie_domain) {
2832 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2833 } else {
2834 /* one domain was already specified, add another one by
2835 * building the string which will be returned along with
2836 * the cookie.
2837 */
2838 char *new_ptr;
2839 int new_len = strlen(curproxy->cookie_domain) +
2840 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2841 new_ptr = malloc(new_len);
2842 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2843 free(curproxy->cookie_domain);
2844 curproxy->cookie_domain = new_ptr;
2845 }
Willy Tarreau31936852010-10-06 16:59:56 +02002846 cur_arg++;
2847 }
2848 else if (!strcmp(args[cur_arg], "maxidle")) {
2849 unsigned int maxidle;
2850 const char *res;
2851
2852 if (!*args[cur_arg + 1]) {
2853 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2854 file, linenum, args[cur_arg]);
2855 err_code |= ERR_ALERT | ERR_FATAL;
2856 goto out;
2857 }
2858
2859 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2860 if (res) {
2861 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2862 file, linenum, *res, args[cur_arg]);
2863 err_code |= ERR_ALERT | ERR_FATAL;
2864 goto out;
2865 }
2866 curproxy->cookie_maxidle = maxidle;
2867 cur_arg++;
2868 }
2869 else if (!strcmp(args[cur_arg], "maxlife")) {
2870 unsigned int maxlife;
2871 const char *res;
2872
2873 if (!*args[cur_arg + 1]) {
2874 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2875 file, linenum, args[cur_arg]);
2876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
2878 }
2879
2880 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2881 if (res) {
2882 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2883 file, linenum, *res, args[cur_arg]);
2884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
2886 }
2887 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002888 cur_arg++;
2889 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002891 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 +02002892 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002895 }
2896 cur_arg++;
2897 }
Willy Tarreau67402132012-05-31 20:40:20 +02002898 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002899 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2900 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002901 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002902 }
2903
Willy Tarreau67402132012-05-31 20:40:20 +02002904 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002905 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2906 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002907 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002908 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002909
Willy Tarreau67402132012-05-31 20:40:20 +02002910 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002911 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2912 file, linenum);
2913 err_code |= ERR_ALERT | ERR_FATAL;
2914 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09002916 else if (!strcmp(args[0], "email-alert")) {
2917 if (*(args[1]) == 0) {
2918 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2919 file, linenum, args[0]);
2920 err_code |= ERR_ALERT | ERR_FATAL;
2921 goto out;
2922 }
2923
2924 if (!strcmp(args[1], "from")) {
2925 if (*(args[1]) == 0) {
2926 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2927 file, linenum, args[1]);
2928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
2930 }
2931 free(curproxy->email_alert.from);
2932 curproxy->email_alert.from = strdup(args[2]);
2933 }
2934 else if (!strcmp(args[1], "mailers")) {
2935 if (*(args[1]) == 0) {
2936 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2937 file, linenum, args[1]);
2938 err_code |= ERR_ALERT | ERR_FATAL;
2939 goto out;
2940 }
2941 free(curproxy->email_alert.mailers.name);
2942 curproxy->email_alert.mailers.name = strdup(args[2]);
2943 }
2944 else if (!strcmp(args[1], "myhostname")) {
2945 if (*(args[1]) == 0) {
2946 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2947 file, linenum, args[1]);
2948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
2950 }
2951 free(curproxy->email_alert.myhostname);
2952 curproxy->email_alert.myhostname = strdup(args[2]);
2953 }
Simon Horman64e34162015-02-06 11:11:57 +09002954 else if (!strcmp(args[1], "level")) {
2955 curproxy->email_alert.level = get_log_level(args[2]);
2956 if (curproxy->email_alert.level < 0) {
2957 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
2958 file, linenum, args[1], args[2]);
2959 err_code |= ERR_ALERT | ERR_FATAL;
2960 goto out;
2961 }
2962 }
Simon Horman9dc49962015-01-30 11:22:59 +09002963 else if (!strcmp(args[1], "to")) {
2964 if (*(args[1]) == 0) {
2965 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2966 file, linenum, args[1]);
2967 err_code |= ERR_ALERT | ERR_FATAL;
2968 goto out;
2969 }
2970 free(curproxy->email_alert.to);
2971 curproxy->email_alert.to = strdup(args[2]);
2972 }
2973 else {
2974 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
2975 file, linenum, args[1]);
2976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
2978 }
Simon Horman64e34162015-02-06 11:11:57 +09002979 /* Indicate that the email_alert is at least partially configured */
2980 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09002981 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09002982 else if (!strcmp(args[0], "external-check")) {
2983 if (*(args[1]) == 0) {
2984 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2985 file, linenum, args[0]);
2986 err_code |= ERR_ALERT | ERR_FATAL;
2987 goto out;
2988 }
2989
2990 if (!strcmp(args[1], "command")) {
2991 if (*(args[1]) == 0) {
2992 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2993 file, linenum, args[1]);
2994 err_code |= ERR_ALERT | ERR_FATAL;
2995 goto out;
2996 }
2997 free(curproxy->check_command);
2998 curproxy->check_command = strdup(args[2]);
2999 }
3000 else if (!strcmp(args[1], "path")) {
3001 if (*(args[1]) == 0) {
3002 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3003 file, linenum, args[1]);
3004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
3006 }
3007 free(curproxy->check_path);
3008 curproxy->check_path = strdup(args[2]);
3009 }
3010 else {
3011 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3012 file, linenum, args[1]);
3013 err_code |= ERR_ALERT | ERR_FATAL;
3014 goto out;
3015 }
3016 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003017 else if (!strcmp(args[0], "persist")) { /* persist */
3018 if (*(args[1]) == 0) {
3019 Alert("parsing [%s:%d] : missing persist method.\n",
3020 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003021 err_code |= ERR_ALERT | ERR_FATAL;
3022 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003023 }
3024
3025 if (!strncmp(args[1], "rdp-cookie", 10)) {
3026 curproxy->options2 |= PR_O2_RDPC_PRST;
3027
Emeric Brunb982a3d2010-01-04 15:45:53 +01003028 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003029 const char *beg, *end;
3030
3031 beg = args[1] + 11;
3032 end = strchr(beg, ')');
3033
3034 if (!end || end == beg) {
3035 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3036 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003037 err_code |= ERR_ALERT | ERR_FATAL;
3038 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003039 }
3040
3041 free(curproxy->rdp_cookie_name);
3042 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3043 curproxy->rdp_cookie_len = end-beg;
3044 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003045 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003046 free(curproxy->rdp_cookie_name);
3047 curproxy->rdp_cookie_name = strdup("msts");
3048 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3049 }
3050 else { /* syntax */
3051 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\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 }
3057 else {
3058 Alert("parsing [%s:%d] : unknown persist method.\n",
3059 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003060 err_code |= ERR_ALERT | ERR_FATAL;
3061 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003062 }
3063 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003064 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003065 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003067 if (curproxy == &defproxy) {
3068 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3069 err_code |= ERR_ALERT | ERR_FATAL;
3070 goto out;
3071 }
3072
Willy Tarreau977b8e42006-12-29 14:19:17 +01003073 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003074 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003075
Willy Tarreaubaaee002006-06-26 02:48:02 +02003076 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003077 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003078 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 }
3082 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003083 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003084 curproxy->appsession_name = strdup(args[1]);
3085 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3086 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003087 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3088 if (err) {
3089 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3090 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003093 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003094 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003095
Willy Tarreau51041c72007-09-09 21:56:53 +02003096 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3097 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003098 err_code |= ERR_ALERT | ERR_ABORT;
3099 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003100 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003101
3102 cur_arg = 6;
3103 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003104 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3105 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003106 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003107 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003108 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003109 } else if (!strcmp(args[cur_arg], "prefix")) {
3110 curproxy->options2 |= PR_O2_AS_PFX;
3111 } else if (!strcmp(args[cur_arg], "mode")) {
3112 if (!*args[cur_arg + 1]) {
3113 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3114 file, linenum, args[0], args[cur_arg]);
3115 err_code |= ERR_ALERT | ERR_FATAL;
3116 goto out;
3117 }
3118
3119 cur_arg++;
3120 if (!strcmp(args[cur_arg], "query-string")) {
3121 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3122 curproxy->options2 |= PR_O2_AS_M_QS;
3123 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3124 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3125 curproxy->options2 |= PR_O2_AS_M_PP;
3126 } else {
3127 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3128 err_code |= ERR_ALERT | ERR_FATAL;
3129 goto out;
3130 }
3131 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003132 cur_arg++;
3133 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003134 } /* Url App Session */
3135 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003136 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003137 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003138
Willy Tarreaubaaee002006-06-26 02:48:02 +02003139 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003140 if (curproxy == &defproxy) {
3141 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3142 err_code |= ERR_ALERT | ERR_FATAL;
3143 goto out;
3144 }
3145
Willy Tarreaubaaee002006-06-26 02:48:02 +02003146 if (*(args[4]) == 0) {
3147 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3148 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003149 err_code |= ERR_ALERT | ERR_FATAL;
3150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003151 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003152 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003153 curproxy->capture_name = strdup(args[2]);
3154 curproxy->capture_namelen = strlen(curproxy->capture_name);
3155 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003156 curproxy->to_log |= LW_COOKIE;
3157 }
3158 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3159 struct cap_hdr *hdr;
3160
3161 if (curproxy == &defproxy) {
3162 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 +02003163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003165 }
3166
3167 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3168 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3169 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003170 err_code |= ERR_ALERT | ERR_FATAL;
3171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003172 }
3173
3174 hdr = calloc(sizeof(struct cap_hdr), 1);
3175 hdr->next = curproxy->req_cap;
3176 hdr->name = strdup(args[3]);
3177 hdr->namelen = strlen(args[3]);
3178 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003179 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 hdr->index = curproxy->nb_req_cap++;
3181 curproxy->req_cap = hdr;
3182 curproxy->to_log |= LW_REQHDR;
3183 }
3184 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3185 struct cap_hdr *hdr;
3186
3187 if (curproxy == &defproxy) {
3188 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 +02003189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003191 }
3192
3193 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3194 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3195 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 }
3199 hdr = calloc(sizeof(struct cap_hdr), 1);
3200 hdr->next = curproxy->rsp_cap;
3201 hdr->name = strdup(args[3]);
3202 hdr->namelen = strlen(args[3]);
3203 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003204 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003205 hdr->index = curproxy->nb_rsp_cap++;
3206 curproxy->rsp_cap = hdr;
3207 curproxy->to_log |= LW_RSPHDR;
3208 }
3209 else {
3210 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3211 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003212 err_code |= ERR_ALERT | ERR_FATAL;
3213 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003214 }
3215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003216 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003217 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003218 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003219
Willy Tarreaubaaee002006-06-26 02:48:02 +02003220 if (*(args[1]) == 0) {
3221 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3222 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003223 err_code |= ERR_ALERT | ERR_FATAL;
3224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003225 }
3226 curproxy->conn_retries = atol(args[1]);
3227 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003228 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003229 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003230
3231 if (curproxy == &defproxy) {
3232 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3233 err_code |= ERR_ALERT | ERR_FATAL;
3234 goto out;
3235 }
3236
Willy Tarreau20b0de52012-12-24 15:45:22 +01003237 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3238 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3239 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3240 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003241 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003242 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3243 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 +01003244 file, linenum, args[0]);
3245 err_code |= ERR_WARN;
3246 }
3247
Willy Tarreauff011f22011-01-06 17:51:27 +01003248 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003249
Willy Tarreauff011f22011-01-06 17:51:27 +01003250 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003251 err_code |= ERR_ALERT | ERR_ABORT;
3252 goto out;
3253 }
3254
Willy Tarreau5002f572014-04-23 01:32:02 +02003255 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003256 err_code |= warnif_cond_conflicts(rule->cond,
3257 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3258 file, linenum);
3259
Willy Tarreauff011f22011-01-06 17:51:27 +01003260 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003261 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003262 else if (!strcmp(args[0], "http-response")) { /* response access control */
3263 struct http_res_rule *rule;
3264
3265 if (curproxy == &defproxy) {
3266 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3267 err_code |= ERR_ALERT | ERR_FATAL;
3268 goto out;
3269 }
3270
3271 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3272 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3273 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3274 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3275 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3276 file, linenum, args[0]);
3277 err_code |= ERR_WARN;
3278 }
3279
3280 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3281
3282 if (!rule) {
3283 err_code |= ERR_ALERT | ERR_ABORT;
3284 goto out;
3285 }
3286
3287 err_code |= warnif_cond_conflicts(rule->cond,
3288 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3289 file, linenum);
3290
3291 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3292 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003293 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3294 /* set the header name and length into the proxy structure */
3295 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3296 err_code |= ERR_WARN;
3297
3298 if (!*args[1]) {
3299 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3300 file, linenum, args[0]);
3301 err_code |= ERR_ALERT | ERR_FATAL;
3302 goto out;
3303 }
3304
3305 /* set the desired header name */
3306 free(curproxy->server_id_hdr_name);
3307 curproxy->server_id_hdr_name = strdup(args[1]);
3308 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3309 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003310 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003311 struct http_req_rule *rule;
3312
Willy Tarreaub099aca2008-10-12 17:26:37 +02003313 if (curproxy == &defproxy) {
3314 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003315 err_code |= ERR_ALERT | ERR_FATAL;
3316 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003317 }
3318
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003319 /* emulate "block" using "http-request block". Since these rules are supposed to
3320 * be processed before all http-request rules, we put them into their own list
3321 * and will insert them at the end.
3322 */
3323 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3324 if (!rule) {
3325 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003326 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003327 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003328 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3329 err_code |= warnif_cond_conflicts(rule->cond,
3330 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3331 file, linenum);
3332 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003333
3334 if (!already_warned(WARN_BLOCK_DEPRECATED))
3335 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]);
3336
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003337 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003338 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003339 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003340
Cyril Bonté99ed3272010-01-24 23:29:44 +01003341 if (curproxy == &defproxy) {
3342 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3343 err_code |= ERR_ALERT | ERR_FATAL;
3344 goto out;
3345 }
3346
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003347 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003348 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3349 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003352 }
3353
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003354 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003355 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003356 err_code |= warnif_cond_conflicts(rule->cond,
3357 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3358 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003359 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003360 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003361 struct switching_rule *rule;
3362
Willy Tarreaub099aca2008-10-12 17:26:37 +02003363 if (curproxy == &defproxy) {
3364 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003365 err_code |= ERR_ALERT | ERR_FATAL;
3366 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003367 }
3368
Willy Tarreau55ea7572007-06-17 19:56:27 +02003369 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003370 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003371
3372 if (*(args[1]) == 0) {
3373 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003374 err_code |= ERR_ALERT | ERR_FATAL;
3375 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003376 }
3377
Willy Tarreauf51658d2014-04-23 01:21:56 +02003378 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3379 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3380 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3381 file, linenum, errmsg);
3382 err_code |= ERR_ALERT | ERR_FATAL;
3383 goto out;
3384 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003385
Willy Tarreauf51658d2014-04-23 01:21:56 +02003386 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003387 }
3388
3389 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3390 rule->cond = cond;
3391 rule->be.name = strdup(args[1]);
3392 LIST_INIT(&rule->list);
3393 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3394 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003395 else if (strcmp(args[0], "use-server") == 0) {
3396 struct server_rule *rule;
3397
3398 if (curproxy == &defproxy) {
3399 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3400 err_code |= ERR_ALERT | ERR_FATAL;
3401 goto out;
3402 }
3403
3404 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3405 err_code |= ERR_WARN;
3406
3407 if (*(args[1]) == 0) {
3408 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3409 err_code |= ERR_ALERT | ERR_FATAL;
3410 goto out;
3411 }
3412
3413 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3414 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3415 file, linenum, args[0]);
3416 err_code |= ERR_ALERT | ERR_FATAL;
3417 goto out;
3418 }
3419
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003420 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3421 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3422 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003423 err_code |= ERR_ALERT | ERR_FATAL;
3424 goto out;
3425 }
3426
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003427 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003428
3429 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3430 rule->cond = cond;
3431 rule->srv.name = strdup(args[1]);
3432 LIST_INIT(&rule->list);
3433 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3434 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3435 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003436 else if ((!strcmp(args[0], "force-persist")) ||
3437 (!strcmp(args[0], "ignore-persist"))) {
3438 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003439
3440 if (curproxy == &defproxy) {
3441 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3442 err_code |= ERR_ALERT | ERR_FATAL;
3443 goto out;
3444 }
3445
3446 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3447 err_code |= ERR_WARN;
3448
Willy Tarreauef6494c2010-01-28 17:12:36 +01003449 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003450 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3451 file, linenum, args[0]);
3452 err_code |= ERR_ALERT | ERR_FATAL;
3453 goto out;
3454 }
3455
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003456 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3457 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3458 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003459 err_code |= ERR_ALERT | ERR_FATAL;
3460 goto out;
3461 }
3462
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003463 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3464 * where force-persist is applied.
3465 */
3466 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003467
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003468 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003469 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003470 if (!strcmp(args[0], "force-persist")) {
3471 rule->type = PERSIST_TYPE_FORCE;
3472 } else {
3473 rule->type = PERSIST_TYPE_IGNORE;
3474 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003475 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003476 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003477 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003478 else if (!strcmp(args[0], "stick-table")) {
3479 int myidx = 1;
3480
Emeric Brun32da3c42010-09-23 18:39:19 +02003481 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003482 curproxy->table.type = (unsigned int)-1;
3483 while (*args[myidx]) {
3484 const char *err;
3485
3486 if (strcmp(args[myidx], "size") == 0) {
3487 myidx++;
3488 if (!*(args[myidx])) {
3489 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3490 file, linenum, args[myidx-1]);
3491 err_code |= ERR_ALERT | ERR_FATAL;
3492 goto out;
3493 }
3494 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3495 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3496 file, linenum, *err, args[myidx-1]);
3497 err_code |= ERR_ALERT | ERR_FATAL;
3498 goto out;
3499 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003500 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003501 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003502 else if (strcmp(args[myidx], "peers") == 0) {
3503 myidx++;
Godbach50523162013-12-11 19:48:57 +08003504 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003505 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3506 file, linenum, args[myidx-1]);
3507 err_code |= ERR_ALERT | ERR_FATAL;
3508 goto out;
Godbach50523162013-12-11 19:48:57 +08003509 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003510 curproxy->table.peers.name = strdup(args[myidx++]);
3511 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003512 else if (strcmp(args[myidx], "expire") == 0) {
3513 myidx++;
3514 if (!*(args[myidx])) {
3515 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3516 file, linenum, args[myidx-1]);
3517 err_code |= ERR_ALERT | ERR_FATAL;
3518 goto out;
3519 }
3520 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3521 if (err) {
3522 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3523 file, linenum, *err, args[myidx-1]);
3524 err_code |= ERR_ALERT | ERR_FATAL;
3525 goto out;
3526 }
3527 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003528 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003529 }
3530 else if (strcmp(args[myidx], "nopurge") == 0) {
3531 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003532 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003533 }
3534 else if (strcmp(args[myidx], "type") == 0) {
3535 myidx++;
3536 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3537 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3538 file, linenum, args[myidx]);
3539 err_code |= ERR_ALERT | ERR_FATAL;
3540 goto out;
3541 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003542 /* myidx already points to next arg */
3543 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003544 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003545 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003546 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003547
3548 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003549 nw = args[myidx];
3550 while (*nw) {
3551 /* the "store" keyword supports a comma-separated list */
3552 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003553 sa = NULL; /* store arg */
3554 while (*nw && *nw != ',') {
3555 if (*nw == '(') {
3556 *nw = 0;
3557 sa = ++nw;
3558 while (*nw != ')') {
3559 if (!*nw) {
3560 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3561 file, linenum, args[0], cw);
3562 err_code |= ERR_ALERT | ERR_FATAL;
3563 goto out;
3564 }
3565 nw++;
3566 }
3567 *nw = '\0';
3568 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003569 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003570 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003571 if (*nw)
3572 *nw++ = '\0';
3573 type = stktable_get_data_type(cw);
3574 if (type < 0) {
3575 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3576 file, linenum, args[0], cw);
3577 err_code |= ERR_ALERT | ERR_FATAL;
3578 goto out;
3579 }
Willy Tarreauac782882010-06-20 10:41:54 +02003580
3581 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3582 switch (err) {
3583 case PE_NONE: break;
3584 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003585 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3586 file, linenum, args[0], cw);
3587 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003588 break;
3589
3590 case PE_ARG_MISSING:
3591 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3592 file, linenum, args[0], cw);
3593 err_code |= ERR_ALERT | ERR_FATAL;
3594 goto out;
3595
3596 case PE_ARG_NOT_USED:
3597 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3598 file, linenum, args[0], cw);
3599 err_code |= ERR_ALERT | ERR_FATAL;
3600 goto out;
3601
3602 default:
3603 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3604 file, linenum, args[0], cw);
3605 err_code |= ERR_ALERT | ERR_FATAL;
3606 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003607 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003608 }
3609 myidx++;
3610 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003611 else {
3612 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3613 file, linenum, args[myidx]);
3614 err_code |= ERR_ALERT | ERR_FATAL;
3615 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003616 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003617 }
3618
3619 if (!curproxy->table.size) {
3620 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3621 file, linenum);
3622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
3624 }
3625
3626 if (curproxy->table.type == (unsigned int)-1) {
3627 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3628 file, linenum);
3629 err_code |= ERR_ALERT | ERR_FATAL;
3630 goto out;
3631 }
3632 }
3633 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003634 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003635 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003636 int myidx = 0;
3637 const char *name = NULL;
3638 int flags;
3639
3640 if (curproxy == &defproxy) {
3641 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3642 err_code |= ERR_ALERT | ERR_FATAL;
3643 goto out;
3644 }
3645
3646 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3647 err_code |= ERR_WARN;
3648 goto out;
3649 }
3650
3651 myidx++;
3652 if ((strcmp(args[myidx], "store") == 0) ||
3653 (strcmp(args[myidx], "store-request") == 0)) {
3654 myidx++;
3655 flags = STK_IS_STORE;
3656 }
3657 else if (strcmp(args[myidx], "store-response") == 0) {
3658 myidx++;
3659 flags = STK_IS_STORE | STK_ON_RSP;
3660 }
3661 else if (strcmp(args[myidx], "match") == 0) {
3662 myidx++;
3663 flags = STK_IS_MATCH;
3664 }
3665 else if (strcmp(args[myidx], "on") == 0) {
3666 myidx++;
3667 flags = STK_IS_MATCH | STK_IS_STORE;
3668 }
3669 else {
3670 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3671 err_code |= ERR_ALERT | ERR_FATAL;
3672 goto out;
3673 }
3674
3675 if (*(args[myidx]) == 0) {
3676 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3677 err_code |= ERR_ALERT | ERR_FATAL;
3678 goto out;
3679 }
3680
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003681 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003682 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003683 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003684 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
3687 }
3688
3689 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003690 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3691 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3692 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003693 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003694 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003695 goto out;
3696 }
3697 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003698 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3699 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3700 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003701 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003702 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003703 goto out;
3704 }
3705 }
3706
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003707 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003708 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003709
Emeric Brunb982a3d2010-01-04 15:45:53 +01003710 if (strcmp(args[myidx], "table") == 0) {
3711 myidx++;
3712 name = args[myidx++];
3713 }
3714
Willy Tarreauef6494c2010-01-28 17:12:36 +01003715 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003716 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3717 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3718 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003719 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003720 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003721 goto out;
3722 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003723 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003724 else if (*(args[myidx])) {
3725 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3726 file, linenum, args[0], args[myidx]);
3727 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003728 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003729 goto out;
3730 }
Emeric Brun97679e72010-09-23 17:56:44 +02003731 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003732 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003733 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003734 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003735
Emeric Brunb982a3d2010-01-04 15:45:53 +01003736 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3737 rule->cond = cond;
3738 rule->expr = expr;
3739 rule->flags = flags;
3740 rule->table.name = name ? strdup(name) : NULL;
3741 LIST_INIT(&rule->list);
3742 if (flags & STK_ON_RSP)
3743 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3744 else
3745 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3746 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003747 else if (!strcmp(args[0], "stats")) {
3748 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3749 curproxy->uri_auth = NULL; /* we must detach from the default config */
3750
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003751 if (!*args[1]) {
3752 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003753 } else if (!strcmp(args[1], "admin")) {
3754 struct stats_admin_rule *rule;
3755
3756 if (curproxy == &defproxy) {
3757 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3758 err_code |= ERR_ALERT | ERR_FATAL;
3759 goto out;
3760 }
3761
3762 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3763 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3764 err_code |= ERR_ALERT | ERR_ABORT;
3765 goto out;
3766 }
3767
3768 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3769 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3770 file, linenum, args[0], args[1]);
3771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
3773 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003774 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3775 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3776 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003777 err_code |= ERR_ALERT | ERR_FATAL;
3778 goto out;
3779 }
3780
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003781 err_code |= warnif_cond_conflicts(cond,
3782 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3783 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003784
3785 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3786 rule->cond = cond;
3787 LIST_INIT(&rule->list);
3788 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003789 } else if (!strcmp(args[1], "uri")) {
3790 if (*(args[2]) == 0) {
3791 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003794 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3795 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003796 err_code |= ERR_ALERT | ERR_ABORT;
3797 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003798 }
3799 } else if (!strcmp(args[1], "realm")) {
3800 if (*(args[2]) == 0) {
3801 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003802 err_code |= ERR_ALERT | ERR_FATAL;
3803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003804 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3805 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003806 err_code |= ERR_ALERT | ERR_ABORT;
3807 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003808 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003809 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003810 unsigned interval;
3811
3812 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3813 if (err) {
3814 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3815 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003816 err_code |= ERR_ALERT | ERR_FATAL;
3817 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003818 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3819 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003820 err_code |= ERR_ALERT | ERR_ABORT;
3821 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003822 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003823 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003824 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003825
3826 if (curproxy == &defproxy) {
3827 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
3830 }
3831
3832 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3833 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3834 err_code |= ERR_ALERT | ERR_ABORT;
3835 goto out;
3836 }
3837
Willy Tarreauff011f22011-01-06 17:51:27 +01003838 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3839 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003840 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3841 file, linenum, args[0]);
3842 err_code |= ERR_WARN;
3843 }
3844
Willy Tarreauff011f22011-01-06 17:51:27 +01003845 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003846
Willy Tarreauff011f22011-01-06 17:51:27 +01003847 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003848 err_code |= ERR_ALERT | ERR_ABORT;
3849 goto out;
3850 }
3851
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003852 err_code |= warnif_cond_conflicts(rule->cond,
3853 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3854 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003855 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003856
Willy Tarreaubaaee002006-06-26 02:48:02 +02003857 } else if (!strcmp(args[1], "auth")) {
3858 if (*(args[2]) == 0) {
3859 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003860 err_code |= ERR_ALERT | ERR_FATAL;
3861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003862 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3863 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003864 err_code |= ERR_ALERT | ERR_ABORT;
3865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003866 }
3867 } else if (!strcmp(args[1], "scope")) {
3868 if (*(args[2]) == 0) {
3869 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003870 err_code |= ERR_ALERT | ERR_FATAL;
3871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003872 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3873 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003874 err_code |= ERR_ALERT | ERR_ABORT;
3875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003876 }
3877 } else if (!strcmp(args[1], "enable")) {
3878 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3879 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003880 err_code |= ERR_ALERT | ERR_ABORT;
3881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003882 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003883 } else if (!strcmp(args[1], "hide-version")) {
3884 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3885 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003886 err_code |= ERR_ALERT | ERR_ABORT;
3887 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003888 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003889 } else if (!strcmp(args[1], "show-legends")) {
3890 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3891 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3892 err_code |= ERR_ALERT | ERR_ABORT;
3893 goto out;
3894 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003895 } else if (!strcmp(args[1], "show-node")) {
3896
3897 if (*args[2]) {
3898 int i;
3899 char c;
3900
3901 for (i=0; args[2][i]; i++) {
3902 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003903 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3904 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003905 break;
3906 }
3907
3908 if (!i || args[2][i]) {
3909 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3910 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3911 file, linenum, args[0], args[1]);
3912 err_code |= ERR_ALERT | ERR_FATAL;
3913 goto out;
3914 }
3915 }
3916
3917 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3918 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3919 err_code |= ERR_ALERT | ERR_ABORT;
3920 goto out;
3921 }
3922 } else if (!strcmp(args[1], "show-desc")) {
3923 char *desc = NULL;
3924
3925 if (*args[2]) {
3926 int i, len=0;
3927 char *d;
3928
Willy Tarreau348acfe2014-04-14 15:00:39 +02003929 for (i = 2; *args[i]; i++)
3930 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003931
3932 desc = d = (char *)calloc(1, len);
3933
Willy Tarreau348acfe2014-04-14 15:00:39 +02003934 d += snprintf(d, desc + len - d, "%s", args[2]);
3935 for (i = 3; *args[i]; i++)
3936 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003937 }
3938
3939 if (!*args[2] && !global.desc)
3940 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3941 file, linenum, args[1]);
3942 else {
3943 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3944 free(desc);
3945 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3946 err_code |= ERR_ALERT | ERR_ABORT;
3947 goto out;
3948 }
3949 free(desc);
3950 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003951 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003952stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003953 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 +01003954 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003955 err_code |= ERR_ALERT | ERR_FATAL;
3956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003957 }
3958 }
3959 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003960 int optnum;
3961
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003962 if (*(args[1]) == '\0') {
3963 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3964 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003965 err_code |= ERR_ALERT | ERR_FATAL;
3966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003967 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003968
3969 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3970 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003971 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3972 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3973 file, linenum, cfg_opts[optnum].name);
3974 err_code |= ERR_ALERT | ERR_FATAL;
3975 goto out;
3976 }
Willy Tarreau93893792009-07-23 13:19:11 +02003977 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3978 err_code |= ERR_WARN;
3979 goto out;
3980 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003981
Willy Tarreau3842f002009-06-14 11:39:52 +02003982 curproxy->no_options &= ~cfg_opts[optnum].val;
3983 curproxy->options &= ~cfg_opts[optnum].val;
3984
3985 switch (kwm) {
3986 case KWM_STD:
3987 curproxy->options |= cfg_opts[optnum].val;
3988 break;
3989 case KWM_NO:
3990 curproxy->no_options |= cfg_opts[optnum].val;
3991 break;
3992 case KWM_DEF: /* already cleared */
3993 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003994 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003995
Willy Tarreau93893792009-07-23 13:19:11 +02003996 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003997 }
3998 }
3999
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004000 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4001 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004002 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4003 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4004 file, linenum, cfg_opts2[optnum].name);
4005 err_code |= ERR_ALERT | ERR_FATAL;
4006 goto out;
4007 }
Willy Tarreau93893792009-07-23 13:19:11 +02004008 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4009 err_code |= ERR_WARN;
4010 goto out;
4011 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004012
Willy Tarreau3842f002009-06-14 11:39:52 +02004013 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4014 curproxy->options2 &= ~cfg_opts2[optnum].val;
4015
4016 switch (kwm) {
4017 case KWM_STD:
4018 curproxy->options2 |= cfg_opts2[optnum].val;
4019 break;
4020 case KWM_NO:
4021 curproxy->no_options2 |= cfg_opts2[optnum].val;
4022 break;
4023 case KWM_DEF: /* already cleared */
4024 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004025 }
Willy Tarreau93893792009-07-23 13:19:11 +02004026 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004027 }
4028 }
4029
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004030 /* HTTP options override each other. They can be cancelled using
4031 * "no option xxx" which only switches to default mode if the mode
4032 * was this one (useful for cancelling options set in defaults
4033 * sections).
4034 */
4035 if (strcmp(args[1], "httpclose") == 0) {
4036 if (kwm == KWM_STD) {
4037 curproxy->options &= ~PR_O_HTTP_MODE;
4038 curproxy->options |= PR_O_HTTP_PCL;
4039 goto out;
4040 }
4041 else if (kwm == KWM_NO) {
4042 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4043 curproxy->options &= ~PR_O_HTTP_MODE;
4044 goto out;
4045 }
4046 }
4047 else if (strcmp(args[1], "forceclose") == 0) {
4048 if (kwm == KWM_STD) {
4049 curproxy->options &= ~PR_O_HTTP_MODE;
4050 curproxy->options |= PR_O_HTTP_FCL;
4051 goto out;
4052 }
4053 else if (kwm == KWM_NO) {
4054 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4055 curproxy->options &= ~PR_O_HTTP_MODE;
4056 goto out;
4057 }
4058 }
4059 else if (strcmp(args[1], "http-server-close") == 0) {
4060 if (kwm == KWM_STD) {
4061 curproxy->options &= ~PR_O_HTTP_MODE;
4062 curproxy->options |= PR_O_HTTP_SCL;
4063 goto out;
4064 }
4065 else if (kwm == KWM_NO) {
4066 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4067 curproxy->options &= ~PR_O_HTTP_MODE;
4068 goto out;
4069 }
4070 }
4071 else if (strcmp(args[1], "http-keep-alive") == 0) {
4072 if (kwm == KWM_STD) {
4073 curproxy->options &= ~PR_O_HTTP_MODE;
4074 curproxy->options |= PR_O_HTTP_KAL;
4075 goto out;
4076 }
4077 else if (kwm == KWM_NO) {
4078 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4079 curproxy->options &= ~PR_O_HTTP_MODE;
4080 goto out;
4081 }
4082 }
4083 else if (strcmp(args[1], "http-tunnel") == 0) {
4084 if (kwm == KWM_STD) {
4085 curproxy->options &= ~PR_O_HTTP_MODE;
4086 curproxy->options |= PR_O_HTTP_TUN;
4087 goto out;
4088 }
4089 else if (kwm == KWM_NO) {
4090 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4091 curproxy->options &= ~PR_O_HTTP_MODE;
4092 goto out;
4093 }
4094 }
4095
Willy Tarreau3842f002009-06-14 11:39:52 +02004096 if (kwm != KWM_STD) {
4097 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004098 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004101 }
4102
Emeric Brun3a058f32009-06-30 18:26:00 +02004103 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004104 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004105 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004106 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004107 if (*(args[2]) != '\0') {
4108 if (!strcmp(args[2], "clf")) {
4109 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004110 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004111 } else {
4112 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02004113 err_code |= ERR_ALERT | ERR_FATAL;
4114 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004115 }
4116 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004117 if (curproxy->conf.logformat_string != default_http_log_format &&
4118 curproxy->conf.logformat_string != default_tcp_log_format &&
4119 curproxy->conf.logformat_string != clf_http_log_format)
4120 free(curproxy->conf.logformat_string);
4121 curproxy->conf.logformat_string = logformat;
4122
4123 free(curproxy->conf.lfs_file);
4124 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4125 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004126 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004127 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004128 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004129 if (curproxy->conf.logformat_string != default_http_log_format &&
4130 curproxy->conf.logformat_string != default_tcp_log_format &&
4131 curproxy->conf.logformat_string != clf_http_log_format)
4132 free(curproxy->conf.logformat_string);
4133 curproxy->conf.logformat_string = default_tcp_log_format;
4134
4135 free(curproxy->conf.lfs_file);
4136 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4137 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004138 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004139 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004140 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004141 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004142 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004143
4144 if (curproxy->cap & PR_CAP_FE)
4145 curproxy->options |= PR_O_TCP_CLI_KA;
4146 if (curproxy->cap & PR_CAP_BE)
4147 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004148 }
4149 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004150 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004151 err_code |= ERR_WARN;
4152
Willy Tarreaubaaee002006-06-26 02:48:02 +02004153 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004154 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004155 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004156 curproxy->options2 &= ~PR_O2_CHK_ANY;
4157 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004158 if (!*args[2]) { /* no argument */
4159 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4160 curproxy->check_len = strlen(DEF_CHECK_REQ);
4161 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004162 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004163 curproxy->check_req = (char *)malloc(reqlen);
4164 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004165 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004166 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004167 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004168 if (*args[4])
4169 reqlen += strlen(args[4]);
4170 else
4171 reqlen += strlen("HTTP/1.0");
4172
4173 curproxy->check_req = (char *)malloc(reqlen);
4174 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004175 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004177 }
4178 else if (!strcmp(args[1], "ssl-hello-chk")) {
4179 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004180 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004181 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004182
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;
Willy Tarreau07a54902010-03-29 18:33:29 +02004186 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004187 }
Willy Tarreau23677902007-05-08 23:50:35 +02004188 else if (!strcmp(args[1], "smtpchk")) {
4189 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004190 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004191 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004192 curproxy->options2 &= ~PR_O2_CHK_ANY;
4193 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004194
4195 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4196 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4197 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4198 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4199 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4200 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4201 curproxy->check_req = (char *)malloc(reqlen);
4202 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4203 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4204 } else {
4205 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4206 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4207 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4208 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4209 }
4210 }
4211 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004212 else if (!strcmp(args[1], "pgsql-check")) {
4213 /* use PostgreSQL request to check servers' health */
4214 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4215 err_code |= ERR_WARN;
4216
4217 free(curproxy->check_req);
4218 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004219 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004220 curproxy->options2 |= PR_O2_PGSQL_CHK;
4221
4222 if (*(args[2])) {
4223 int cur_arg = 2;
4224
4225 while (*(args[cur_arg])) {
4226 if (strcmp(args[cur_arg], "user") == 0) {
4227 char * packet;
4228 uint32_t packet_len;
4229 uint32_t pv;
4230
4231 /* suboption header - needs additional argument for it */
4232 if (*(args[cur_arg+1]) == 0) {
4233 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4234 file, linenum, args[0], args[1], args[cur_arg]);
4235 err_code |= ERR_ALERT | ERR_FATAL;
4236 goto out;
4237 }
4238
4239 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4240 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4241 pv = htonl(0x30000); /* protocol version 3.0 */
4242
4243 packet = (char*) calloc(1, packet_len);
4244
4245 memcpy(packet + 4, &pv, 4);
4246
4247 /* copy "user" */
4248 memcpy(packet + 8, "user", 4);
4249
4250 /* copy username */
4251 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4252
4253 free(curproxy->check_req);
4254 curproxy->check_req = packet;
4255 curproxy->check_len = packet_len;
4256
4257 packet_len = htonl(packet_len);
4258 memcpy(packet, &packet_len, 4);
4259 cur_arg += 2;
4260 } else {
4261 /* unknown suboption - catchall */
4262 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4263 file, linenum, args[0], args[1]);
4264 err_code |= ERR_ALERT | ERR_FATAL;
4265 goto out;
4266 }
4267 } /* end while loop */
4268 }
4269 }
4270
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004271 else if (!strcmp(args[1], "redis-check")) {
4272 /* use REDIS PING request to check servers' health */
4273 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4274 err_code |= ERR_WARN;
4275
4276 free(curproxy->check_req);
4277 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004278 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004279 curproxy->options2 |= PR_O2_REDIS_CHK;
4280
4281 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4282 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4283 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4284 }
4285
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004286 else if (!strcmp(args[1], "mysql-check")) {
4287 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004288 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4289 err_code |= ERR_WARN;
4290
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004291 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004292 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004293 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004294 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004295
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004296 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004297 * const char mysql40_client_auth_pkt[] = {
4298 * "\x0e\x00\x00" // packet length
4299 * "\x01" // packet number
4300 * "\x00\x00" // client capabilities
4301 * "\x00\x00\x01" // max packet
4302 * "haproxy\x00" // username (null terminated string)
4303 * "\x00" // filler (always 0x00)
4304 * "\x01\x00\x00" // packet length
4305 * "\x00" // packet number
4306 * "\x01" // COM_QUIT command
4307 * };
4308 */
4309
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004310 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4311 * const char mysql41_client_auth_pkt[] = {
4312 * "\x0e\x00\x00\" // packet length
4313 * "\x01" // packet number
4314 * "\x00\x00\x00\x00" // client capabilities
4315 * "\x00\x00\x00\x01" // max packet
4316 * "\x21" // character set (UTF-8)
4317 * char[23] // All zeroes
4318 * "haproxy\x00" // username (null terminated string)
4319 * "\x00" // filler (always 0x00)
4320 * "\x01\x00\x00" // packet length
4321 * "\x00" // packet number
4322 * "\x01" // COM_QUIT command
4323 * };
4324 */
4325
4326
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004327 if (*(args[2])) {
4328 int cur_arg = 2;
4329
4330 while (*(args[cur_arg])) {
4331 if (strcmp(args[cur_arg], "user") == 0) {
4332 char *mysqluser;
4333 int packetlen, reqlen, userlen;
4334
4335 /* suboption header - needs additional argument for it */
4336 if (*(args[cur_arg+1]) == 0) {
4337 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4338 file, linenum, args[0], args[1], args[cur_arg]);
4339 err_code |= ERR_ALERT | ERR_FATAL;
4340 goto out;
4341 }
4342 mysqluser = args[cur_arg + 1];
4343 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004344
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004345 if (*(args[cur_arg+2])) {
4346 if (!strcmp(args[cur_arg+2], "post-41")) {
4347 packetlen = userlen + 7 + 27;
4348 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004349
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004350 free(curproxy->check_req);
4351 curproxy->check_req = (char *)calloc(1, reqlen);
4352 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004353
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004354 snprintf(curproxy->check_req, 4, "%c%c%c",
4355 ((unsigned char) packetlen & 0xff),
4356 ((unsigned char) (packetlen >> 8) & 0xff),
4357 ((unsigned char) (packetlen >> 16) & 0xff));
4358
4359 curproxy->check_req[3] = 1;
4360 curproxy->check_req[5] = 130;
4361 curproxy->check_req[11] = 1;
4362 curproxy->check_req[12] = 33;
4363 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4364 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4365 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4366 cur_arg += 3;
4367 } else {
4368 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4369 err_code |= ERR_ALERT | ERR_FATAL;
4370 goto out;
4371 }
4372 } else {
4373 packetlen = userlen + 7;
4374 reqlen = packetlen + 9;
4375
4376 free(curproxy->check_req);
4377 curproxy->check_req = (char *)calloc(1, reqlen);
4378 curproxy->check_len = reqlen;
4379
4380 snprintf(curproxy->check_req, 4, "%c%c%c",
4381 ((unsigned char) packetlen & 0xff),
4382 ((unsigned char) (packetlen >> 8) & 0xff),
4383 ((unsigned char) (packetlen >> 16) & 0xff));
4384
4385 curproxy->check_req[3] = 1;
4386 curproxy->check_req[5] = 128;
4387 curproxy->check_req[8] = 1;
4388 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4389 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4390 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4391 cur_arg += 2;
4392 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004393 } else {
4394 /* unknown suboption - catchall */
4395 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4396 file, linenum, args[0], args[1]);
4397 err_code |= ERR_ALERT | ERR_FATAL;
4398 goto out;
4399 }
4400 } /* end while loop */
4401 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004402 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004403 else if (!strcmp(args[1], "ldap-check")) {
4404 /* use LDAP request to check servers' health */
4405 free(curproxy->check_req);
4406 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004407 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004408 curproxy->options2 |= PR_O2_LDAP_CHK;
4409
4410 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4411 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4412 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4413 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004414 else if (!strcmp(args[1], "tcp-check")) {
4415 /* use raw TCPCHK send/expect to check servers' health */
4416 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4417 err_code |= ERR_WARN;
4418
4419 free(curproxy->check_req);
4420 curproxy->check_req = NULL;
4421 curproxy->options2 &= ~PR_O2_CHK_ANY;
4422 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4423 }
Simon Horman98637e52014-06-20 12:30:16 +09004424 else if (!strcmp(args[1], "external-check")) {
4425 /* excute an external command to check servers' health */
4426 free(curproxy->check_req);
4427 curproxy->check_req = NULL;
4428 curproxy->options2 &= ~PR_O2_CHK_ANY;
4429 curproxy->options2 |= PR_O2_EXT_CHK;
4430 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004431 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004432 int cur_arg;
4433
4434 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4435 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004436 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004437
Willy Tarreau87cf5142011-08-19 22:57:24 +02004438 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004439
4440 free(curproxy->fwdfor_hdr_name);
4441 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4442 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4443
4444 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4445 cur_arg = 2;
4446 while (*(args[cur_arg])) {
4447 if (!strcmp(args[cur_arg], "except")) {
4448 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004449 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004450 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4451 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004452 err_code |= ERR_ALERT | ERR_FATAL;
4453 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004454 }
4455 /* flush useless bits */
4456 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004457 cur_arg += 2;
4458 } else if (!strcmp(args[cur_arg], "header")) {
4459 /* suboption header - needs additional argument for it */
4460 if (*(args[cur_arg+1]) == 0) {
4461 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4462 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004463 err_code |= ERR_ALERT | ERR_FATAL;
4464 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004465 }
4466 free(curproxy->fwdfor_hdr_name);
4467 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4468 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4469 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004470 } else if (!strcmp(args[cur_arg], "if-none")) {
4471 curproxy->options &= ~PR_O_FF_ALWAYS;
4472 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004473 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004474 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004475 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004476 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004477 err_code |= ERR_ALERT | ERR_FATAL;
4478 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004479 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004480 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004481 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004482 else if (!strcmp(args[1], "originalto")) {
4483 int cur_arg;
4484
4485 /* insert x-original-to field, but not for the IP address listed as an except.
4486 * set default options (ie: bitfield, header name, etc)
4487 */
4488
4489 curproxy->options |= PR_O_ORGTO;
4490
4491 free(curproxy->orgto_hdr_name);
4492 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4493 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4494
Willy Tarreau87cf5142011-08-19 22:57:24 +02004495 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004496 cur_arg = 2;
4497 while (*(args[cur_arg])) {
4498 if (!strcmp(args[cur_arg], "except")) {
4499 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004500 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 +02004501 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4502 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004503 err_code |= ERR_ALERT | ERR_FATAL;
4504 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004505 }
4506 /* flush useless bits */
4507 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4508 cur_arg += 2;
4509 } else if (!strcmp(args[cur_arg], "header")) {
4510 /* suboption header - needs additional argument for it */
4511 if (*(args[cur_arg+1]) == 0) {
4512 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4513 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004514 err_code |= ERR_ALERT | ERR_FATAL;
4515 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004516 }
4517 free(curproxy->orgto_hdr_name);
4518 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4519 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4520 cur_arg += 2;
4521 } else {
4522 /* unknown suboption - catchall */
4523 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4524 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004525 err_code |= ERR_ALERT | ERR_FATAL;
4526 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004527 }
4528 } /* end while loop */
4529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004530 else {
4531 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004532 err_code |= ERR_ALERT | ERR_FATAL;
4533 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004534 }
Willy Tarreau93893792009-07-23 13:19:11 +02004535 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004536 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004537 else if (!strcmp(args[0], "default_backend")) {
4538 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004539 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004540
4541 if (*(args[1]) == 0) {
4542 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004543 err_code |= ERR_ALERT | ERR_FATAL;
4544 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004545 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004546 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004547 curproxy->defbe.name = strdup(args[1]);
4548 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004549 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004550 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004551 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004552
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004553 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4554 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 +01004555 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004556 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004557 /* enable reconnections to dispatch */
4558 curproxy->options |= PR_O_REDISP;
4559 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004560 else if (!strcmp(args[0], "http-check")) {
4561 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004562 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004563
4564 if (strcmp(args[1], "disable-on-404") == 0) {
4565 /* enable a graceful server shutdown on an HTTP 404 response */
4566 curproxy->options |= PR_O_DISABLE404;
4567 }
Willy Tarreauef781042010-01-27 11:53:01 +01004568 else if (strcmp(args[1], "send-state") == 0) {
4569 /* enable emission of the apparent state of a server in HTTP checks */
4570 curproxy->options2 |= PR_O2_CHK_SNDST;
4571 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004572 else if (strcmp(args[1], "expect") == 0) {
4573 const char *ptr_arg;
4574 int cur_arg;
4575
4576 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4577 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4578 err_code |= ERR_ALERT | ERR_FATAL;
4579 goto out;
4580 }
4581
4582 cur_arg = 2;
4583 /* consider exclamation marks, sole or at the beginning of a word */
4584 while (*(ptr_arg = args[cur_arg])) {
4585 while (*ptr_arg == '!') {
4586 curproxy->options2 ^= PR_O2_EXP_INV;
4587 ptr_arg++;
4588 }
4589 if (*ptr_arg)
4590 break;
4591 cur_arg++;
4592 }
4593 /* now ptr_arg points to the beginning of a word past any possible
4594 * exclamation mark, and cur_arg is the argument which holds this word.
4595 */
4596 if (strcmp(ptr_arg, "status") == 0) {
4597 if (!*(args[cur_arg + 1])) {
4598 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4599 file, linenum, args[0], args[1], ptr_arg);
4600 err_code |= ERR_ALERT | ERR_FATAL;
4601 goto out;
4602 }
4603 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004604 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004605 curproxy->expect_str = strdup(args[cur_arg + 1]);
4606 }
4607 else if (strcmp(ptr_arg, "string") == 0) {
4608 if (!*(args[cur_arg + 1])) {
4609 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4610 file, linenum, args[0], args[1], ptr_arg);
4611 err_code |= ERR_ALERT | ERR_FATAL;
4612 goto out;
4613 }
4614 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004615 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004616 curproxy->expect_str = strdup(args[cur_arg + 1]);
4617 }
4618 else if (strcmp(ptr_arg, "rstatus") == 0) {
4619 if (!*(args[cur_arg + 1])) {
4620 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4621 file, linenum, args[0], args[1], ptr_arg);
4622 err_code |= ERR_ALERT | ERR_FATAL;
4623 goto out;
4624 }
4625 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004626 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004627 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004628 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004629 free(curproxy->expect_regex);
4630 curproxy->expect_regex = NULL;
4631 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004632 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004633 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4634 error = NULL;
4635 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4636 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4637 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4638 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004639 err_code |= ERR_ALERT | ERR_FATAL;
4640 goto out;
4641 }
4642 }
4643 else if (strcmp(ptr_arg, "rstring") == 0) {
4644 if (!*(args[cur_arg + 1])) {
4645 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4646 file, linenum, args[0], args[1], ptr_arg);
4647 err_code |= ERR_ALERT | ERR_FATAL;
4648 goto out;
4649 }
4650 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004651 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004652 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004653 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004654 free(curproxy->expect_regex);
4655 curproxy->expect_regex = NULL;
4656 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004657 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004658 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4659 error = NULL;
4660 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4661 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4662 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4663 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004664 err_code |= ERR_ALERT | ERR_FATAL;
4665 goto out;
4666 }
4667 }
4668 else {
4669 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4670 file, linenum, args[0], args[1], ptr_arg);
4671 err_code |= ERR_ALERT | ERR_FATAL;
4672 goto out;
4673 }
4674 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004675 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004676 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 +02004677 err_code |= ERR_ALERT | ERR_FATAL;
4678 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004679 }
4680 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004681 else if (!strcmp(args[0], "tcp-check")) {
4682 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4683 err_code |= ERR_WARN;
4684
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004685 if (strcmp(args[1], "connect") == 0) {
4686 const char *ptr_arg;
4687 int cur_arg;
4688 struct tcpcheck_rule *tcpcheck;
4689 struct list *l;
4690
4691 /* check if first rule is also a 'connect' action */
4692 l = (struct list *)&curproxy->tcpcheck_rules;
4693 if (l->p != l->n) {
4694 tcpcheck = (struct tcpcheck_rule *)l->n;
4695 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4696 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4697 file, linenum);
4698 err_code |= ERR_ALERT | ERR_FATAL;
4699 goto out;
4700 }
4701 }
4702
4703 cur_arg = 2;
4704 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4705 tcpcheck->action = TCPCHK_ACT_CONNECT;
4706
4707 /* parsing each parameters to fill up the rule */
4708 while (*(ptr_arg = args[cur_arg])) {
4709 /* tcp port */
4710 if (strcmp(args[cur_arg], "port") == 0) {
4711 if ( (atol(args[cur_arg + 1]) > 65535) ||
4712 (atol(args[cur_arg + 1]) < 1) ){
4713 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4714 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4715 err_code |= ERR_ALERT | ERR_FATAL;
4716 goto out;
4717 }
4718 tcpcheck->port = atol(args[cur_arg + 1]);
4719 cur_arg += 2;
4720 }
4721 /* send proxy protocol */
4722 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4723 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4724 cur_arg++;
4725 }
4726#ifdef USE_OPENSSL
4727 else if (strcmp(args[cur_arg], "ssl") == 0) {
4728 curproxy->options |= PR_O_TCPCHK_SSL;
4729 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4730 cur_arg++;
4731 }
4732#endif /* USE_OPENSSL */
4733 else {
4734#ifdef USE_OPENSSL
4735 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4736#else /* USE_OPENSSL */
4737 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4738#endif /* USE_OPENSSL */
4739 file, linenum, args[0], args[1], args[cur_arg]);
4740 err_code |= ERR_ALERT | ERR_FATAL;
4741 goto out;
4742 }
4743
4744 }
4745
4746 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4747 }
4748 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004749 if (! *(args[2]) ) {
4750 /* SEND string expected */
4751 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4752 file, linenum, args[0], args[1], args[2]);
4753 err_code |= ERR_ALERT | ERR_FATAL;
4754 goto out;
4755 } else {
4756 struct tcpcheck_rule *tcpcheck;
4757
4758 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4759
4760 tcpcheck->action = TCPCHK_ACT_SEND;
4761 tcpcheck->string_len = strlen(args[2]);
4762 tcpcheck->string = strdup(args[2]);
4763 tcpcheck->expect_regex = NULL;
4764
4765 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4766 }
4767 }
4768 else if (strcmp(args[1], "send-binary") == 0) {
4769 if (! *(args[2]) ) {
4770 /* SEND binary string expected */
4771 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4772 file, linenum, args[0], args[1], args[2]);
4773 err_code |= ERR_ALERT | ERR_FATAL;
4774 goto out;
4775 } else {
4776 struct tcpcheck_rule *tcpcheck;
4777 char *err = NULL;
4778
4779 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4780
4781 tcpcheck->action = TCPCHK_ACT_SEND;
4782 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4783 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4784 file, linenum, args[0], args[1], args[2], err);
4785 err_code |= ERR_ALERT | ERR_FATAL;
4786 goto out;
4787 }
4788 tcpcheck->expect_regex = NULL;
4789
4790 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4791 }
4792 }
4793 else if (strcmp(args[1], "expect") == 0) {
4794 const char *ptr_arg;
4795 int cur_arg;
4796 int inverse = 0;
4797
4798 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4799 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4800 err_code |= ERR_ALERT | ERR_FATAL;
4801 goto out;
4802 }
4803
4804 cur_arg = 2;
4805 /* consider exclamation marks, sole or at the beginning of a word */
4806 while (*(ptr_arg = args[cur_arg])) {
4807 while (*ptr_arg == '!') {
4808 inverse = !inverse;
4809 ptr_arg++;
4810 }
4811 if (*ptr_arg)
4812 break;
4813 cur_arg++;
4814 }
4815 /* now ptr_arg points to the beginning of a word past any possible
4816 * exclamation mark, and cur_arg is the argument which holds this word.
4817 */
4818 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004819 struct tcpcheck_rule *tcpcheck;
4820 char *err = NULL;
4821
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004822 if (!*(args[cur_arg + 1])) {
4823 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4824 file, linenum, args[0], args[1], ptr_arg);
4825 err_code |= ERR_ALERT | ERR_FATAL;
4826 goto out;
4827 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004828
4829 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4830
4831 tcpcheck->action = TCPCHK_ACT_EXPECT;
4832 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4833 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4834 file, linenum, args[0], args[1], args[2], err);
4835 err_code |= ERR_ALERT | ERR_FATAL;
4836 goto out;
4837 }
4838 tcpcheck->expect_regex = NULL;
4839 tcpcheck->inverse = inverse;
4840
4841 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4842 }
4843 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004844 struct tcpcheck_rule *tcpcheck;
4845
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004846 if (!*(args[cur_arg + 1])) {
4847 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4848 file, linenum, args[0], args[1], ptr_arg);
4849 err_code |= ERR_ALERT | ERR_FATAL;
4850 goto out;
4851 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004852
4853 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4854
4855 tcpcheck->action = TCPCHK_ACT_EXPECT;
4856 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4857 tcpcheck->string = strdup(args[cur_arg + 1]);
4858 tcpcheck->expect_regex = NULL;
4859 tcpcheck->inverse = inverse;
4860
4861 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4862 }
4863 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004864 struct tcpcheck_rule *tcpcheck;
4865
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004866 if (!*(args[cur_arg + 1])) {
4867 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4868 file, linenum, args[0], args[1], ptr_arg);
4869 err_code |= ERR_ALERT | ERR_FATAL;
4870 goto out;
4871 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004872
4873 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4874
4875 tcpcheck->action = TCPCHK_ACT_EXPECT;
4876 tcpcheck->string_len = 0;
4877 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004878 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4879 error = NULL;
4880 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4881 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4882 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4883 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004884 err_code |= ERR_ALERT | ERR_FATAL;
4885 goto out;
4886 }
4887 tcpcheck->inverse = inverse;
4888
4889 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4890 }
4891 else {
4892 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4893 file, linenum, args[0], args[1], ptr_arg);
4894 err_code |= ERR_ALERT | ERR_FATAL;
4895 goto out;
4896 }
4897 }
4898 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004899 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
4902 }
4903 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004904 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004905 if (curproxy == &defproxy) {
4906 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004907 err_code |= ERR_ALERT | ERR_FATAL;
4908 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004909 }
4910
Willy Tarreaub80c2302007-11-30 20:51:32 +01004911 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004912 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004913
4914 if (strcmp(args[1], "fail") == 0) {
4915 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004916 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004917 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4918 file, linenum, args[0], args[1]);
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
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004923 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4924 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4925 file, linenum, args[0], args[1], errmsg);
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 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4930 }
4931 else {
4932 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004933 err_code |= ERR_ALERT | ERR_FATAL;
4934 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004935 }
4936 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004937#ifdef TPROXY
4938 else if (!strcmp(args[0], "transparent")) {
4939 /* enable transparent proxy connections */
4940 curproxy->options |= PR_O_TRANSP;
4941 }
4942#endif
4943 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004944 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004945 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004946
Willy Tarreaubaaee002006-06-26 02:48:02 +02004947 if (*(args[1]) == 0) {
4948 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004949 err_code |= ERR_ALERT | ERR_FATAL;
4950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004951 }
4952 curproxy->maxconn = atol(args[1]);
4953 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004954 else if (!strcmp(args[0], "backlog")) { /* backlog */
4955 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004956 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004957
4958 if (*(args[1]) == 0) {
4959 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004960 err_code |= ERR_ALERT | ERR_FATAL;
4961 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004962 }
4963 curproxy->backlog = atol(args[1]);
4964 }
Willy Tarreau86034312006-12-29 00:10:33 +01004965 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004966 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004967 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004968
Willy Tarreau86034312006-12-29 00:10:33 +01004969 if (*(args[1]) == 0) {
4970 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004971 err_code |= ERR_ALERT | ERR_FATAL;
4972 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004973 }
4974 curproxy->fullconn = atol(args[1]);
4975 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004976 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4977 if (*(args[1]) == 0) {
4978 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004979 err_code |= ERR_ALERT | ERR_FATAL;
4980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004982 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4983 if (err) {
4984 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4985 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004986 err_code |= ERR_ALERT | ERR_FATAL;
4987 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004988 }
4989 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004990 }
4991 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004992 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004993 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004994 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004995
Willy Tarreaubaaee002006-06-26 02:48:02 +02004996 if (curproxy == &defproxy) {
4997 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004998 err_code |= ERR_ALERT | ERR_FATAL;
4999 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005000 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005001 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005002 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005003
Willy Tarreau902636f2013-03-10 19:44:48 +01005004 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005005 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005006 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005007 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005008 goto out;
5009 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005010
5011 proto = protocol_by_family(sk->ss_family);
5012 if (!proto || !proto->connect) {
5013 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5014 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005015 err_code |= ERR_ALERT | ERR_FATAL;
5016 goto out;
5017 }
5018
5019 if (port1 != port2) {
5020 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5021 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005022 err_code |= ERR_ALERT | ERR_FATAL;
5023 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005025
5026 if (!port1) {
5027 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5028 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005029 err_code |= ERR_ALERT | ERR_FATAL;
5030 goto out;
5031 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005032
Willy Tarreaud5191e72010-02-09 20:50:45 +01005033 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005034 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005035 }
5036 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005037 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005038 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005039
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005040 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5041 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005042 err_code |= ERR_ALERT | ERR_FATAL;
5043 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005044 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005045 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005046 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005047 /**
5048 * The syntax for hash-type config element is
5049 * hash-type {map-based|consistent} [[<algo>] avalanche]
5050 *
5051 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5052 */
5053 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005054
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005055 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5056 err_code |= ERR_WARN;
5057
5058 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005059 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5060 }
5061 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005062 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5063 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005064 else if (strcmp(args[1], "avalanche") == 0) {
5065 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]);
5066 err_code |= ERR_ALERT | ERR_FATAL;
5067 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005068 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005069 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005070 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005071 err_code |= ERR_ALERT | ERR_FATAL;
5072 goto out;
5073 }
Bhaskar98634f02013-10-29 23:30:51 -04005074
5075 /* set the hash function to use */
5076 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005077 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005078 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005079
5080 /* if consistent with no argument, then avalanche modifier is also applied */
5081 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5082 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005083 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005084 /* set the hash function */
5085 if (!strcmp(args[2], "sdbm")) {
5086 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5087 }
5088 else if (!strcmp(args[2], "djb2")) {
5089 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005090 }
5091 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005092 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005093 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005094 else if (!strcmp(args[2], "crc32")) {
5095 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5096 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005097 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005098 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 -05005099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
5101 }
5102
5103 /* set the hash modifier */
5104 if (!strcmp(args[3], "avalanche")) {
5105 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5106 }
5107 else if (*args[3]) {
5108 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5109 err_code |= ERR_ALERT | ERR_FATAL;
5110 goto out;
5111 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005112 }
William Lallemanda73203e2012-03-12 12:48:57 +01005113 }
William Lallemanda73203e2012-03-12 12:48:57 +01005114 else if (strcmp(args[0], "unique-id-format") == 0) {
5115 if (!*(args[1])) {
5116 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5117 err_code |= ERR_ALERT | ERR_FATAL;
5118 goto out;
5119 }
William Lallemand3203ff42012-11-11 17:30:56 +01005120 if (*(args[2])) {
5121 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5122 err_code |= ERR_ALERT | ERR_FATAL;
5123 goto out;
5124 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005125 free(curproxy->conf.uniqueid_format_string);
5126 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005127
Willy Tarreau62a61232013-04-12 18:13:46 +02005128 free(curproxy->conf.uif_file);
5129 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5130 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005131 }
William Lallemanda73203e2012-03-12 12:48:57 +01005132
5133 else if (strcmp(args[0], "unique-id-header") == 0) {
5134 if (!*(args[1])) {
5135 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5136 err_code |= ERR_ALERT | ERR_FATAL;
5137 goto out;
5138 }
5139 free(curproxy->header_unique_id);
5140 curproxy->header_unique_id = strdup(args[1]);
5141 }
5142
William Lallemand723b73a2012-02-08 16:37:49 +01005143 else if (strcmp(args[0], "log-format") == 0) {
5144 if (!*(args[1])) {
5145 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5146 err_code |= ERR_ALERT | ERR_FATAL;
5147 goto out;
5148 }
William Lallemand3203ff42012-11-11 17:30:56 +01005149 if (*(args[2])) {
5150 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5151 err_code |= ERR_ALERT | ERR_FATAL;
5152 goto out;
5153 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005154
Willy Tarreau62a61232013-04-12 18:13:46 +02005155 if (curproxy->conf.logformat_string != default_http_log_format &&
5156 curproxy->conf.logformat_string != default_tcp_log_format &&
5157 curproxy->conf.logformat_string != clf_http_log_format)
5158 free(curproxy->conf.logformat_string);
5159 curproxy->conf.logformat_string = strdup(args[1]);
5160
5161 free(curproxy->conf.lfs_file);
5162 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5163 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005164
5165 /* get a chance to improve log-format error reporting by
5166 * reporting the correct line-number when possible.
5167 */
5168 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5169 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5170 file, linenum, curproxy->id);
5171 err_code |= ERR_WARN;
5172 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005173 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005174 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5175 if (*(args[1]) == 0) {
5176 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5177 err_code |= ERR_ALERT | ERR_FATAL;
5178 goto out;
5179 }
5180 free(curproxy->log_tag);
5181 curproxy->log_tag = strdup(args[1]);
5182 }
William Lallemand0f99e342011-10-12 17:50:54 +02005183 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5184 /* delete previous herited or defined syslog servers */
5185 struct logsrv *back;
5186
5187 if (*(args[1]) != 0) {
5188 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5189 err_code |= ERR_ALERT | ERR_FATAL;
5190 goto out;
5191 }
5192
William Lallemand723b73a2012-02-08 16:37:49 +01005193 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5194 LIST_DEL(&tmplogsrv->list);
5195 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005196 }
5197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005198 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005199 struct logsrv *logsrv;
5200
Willy Tarreaubaaee002006-06-26 02:48:02 +02005201 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005202 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005203 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005204 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005205 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005206 LIST_INIT(&node->list);
5207 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5208 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005209 }
5210 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005211 struct sockaddr_storage *sk;
5212 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005213 int arg = 0;
5214 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005215
5216 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005217
Willy Tarreau18324f52014-06-27 18:10:07 +02005218 /* just after the address, a length may be specified */
5219 if (strcmp(args[arg+2], "len") == 0) {
5220 len = atoi(args[arg+3]);
5221 if (len < 80 || len > 65535) {
5222 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5223 file, linenum, args[arg+3]);
5224 err_code |= ERR_ALERT | ERR_FATAL;
5225 goto out;
5226 }
5227 logsrv->maxlen = len;
5228
5229 /* skip these two args */
5230 arg += 2;
5231 }
5232 else
5233 logsrv->maxlen = MAX_SYSLOG_LEN;
5234
5235 if (logsrv->maxlen > global.max_syslog_len) {
5236 global.max_syslog_len = logsrv->maxlen;
5237 logline = realloc(logline, global.max_syslog_len + 1);
5238 }
5239
5240 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005241 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005242 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005243 err_code |= ERR_ALERT | ERR_FATAL;
5244 goto out;
5245
Willy Tarreaubaaee002006-06-26 02:48:02 +02005246 }
5247
William Lallemand0f99e342011-10-12 17:50:54 +02005248 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005249 if (*(args[arg+3])) {
5250 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005251 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005252 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005253 err_code |= ERR_ALERT | ERR_FATAL;
5254 goto out;
5255
Willy Tarreaubaaee002006-06-26 02:48:02 +02005256 }
5257 }
5258
William Lallemand0f99e342011-10-12 17:50:54 +02005259 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005260 if (*(args[arg+4])) {
5261 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005262 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005263 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005264 err_code |= ERR_ALERT | ERR_FATAL;
5265 goto out;
5266
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005267 }
5268 }
5269
Willy Tarreau902636f2013-03-10 19:44:48 +01005270 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005271 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005272 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005273 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005274 goto out;
5275 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005276
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005277 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005278
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005279 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005280 if (port1 != port2) {
5281 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5282 file, linenum, args[0], args[1]);
5283 err_code |= ERR_ALERT | ERR_FATAL;
5284 goto out;
5285 }
5286
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005287 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005288 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005289 }
William Lallemand0f99e342011-10-12 17:50:54 +02005290
5291 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292 }
5293 else {
5294 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5295 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005296 err_code |= ERR_ALERT | ERR_FATAL;
5297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005298 }
5299 }
5300 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005301 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005302 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005303 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005304 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005305
Willy Tarreau977b8e42006-12-29 14:19:17 +01005306 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005307 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005308
Willy Tarreaubaaee002006-06-26 02:48:02 +02005309 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005310 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5311 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005312 err_code |= ERR_ALERT | ERR_FATAL;
5313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005314 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005315
5316 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005317 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5318 free(curproxy->conn_src.iface_name);
5319 curproxy->conn_src.iface_name = NULL;
5320 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005321
Willy Tarreau902636f2013-03-10 19:44:48 +01005322 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005323 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005324 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005325 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005326 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005327 goto out;
5328 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005329
5330 proto = protocol_by_family(sk->ss_family);
5331 if (!proto || !proto->connect) {
5332 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005333 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005334 err_code |= ERR_ALERT | ERR_FATAL;
5335 goto out;
5336 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005337
5338 if (port1 != port2) {
5339 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5340 file, linenum, args[0], args[1]);
5341 err_code |= ERR_ALERT | ERR_FATAL;
5342 goto out;
5343 }
5344
Willy Tarreauef9a3602012-12-08 22:29:20 +01005345 curproxy->conn_src.source_addr = *sk;
5346 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005347
5348 cur_arg = 2;
5349 while (*(args[cur_arg])) {
5350 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005351#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5352#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005353 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005354 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\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#endif
5360 if (!*args[cur_arg + 1]) {
5361 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5362 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005363 err_code |= ERR_ALERT | ERR_FATAL;
5364 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005365 }
5366
5367 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005368 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5369 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005370 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005371 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5372 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005373 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5374 char *name, *end;
5375
5376 name = args[cur_arg+1] + 7;
5377 while (isspace(*name))
5378 name++;
5379
5380 end = name;
5381 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5382 end++;
5383
Willy Tarreauef9a3602012-12-08 22:29:20 +01005384 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5385 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5386 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5387 curproxy->conn_src.bind_hdr_len = end - name;
5388 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5389 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5390 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005391
5392 /* now look for an occurrence number */
5393 while (isspace(*end))
5394 end++;
5395 if (*end == ',') {
5396 end++;
5397 name = end;
5398 if (*end == '-')
5399 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005400 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005401 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005402 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005403 }
5404
Willy Tarreauef9a3602012-12-08 22:29:20 +01005405 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005406 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5407 " occurrences values smaller than %d.\n",
5408 file, linenum, MAX_HDR_HISTORY);
5409 err_code |= ERR_ALERT | ERR_FATAL;
5410 goto out;
5411 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005412 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005413 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005414
Willy Tarreau902636f2013-03-10 19:44:48 +01005415 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005416 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005417 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005418 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005419 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005420 goto out;
5421 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005422
5423 proto = protocol_by_family(sk->ss_family);
5424 if (!proto || !proto->connect) {
5425 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5426 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005427 err_code |= ERR_ALERT | ERR_FATAL;
5428 goto out;
5429 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005430
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005431 if (port1 != port2) {
5432 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5433 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005434 err_code |= ERR_ALERT | ERR_FATAL;
5435 goto out;
5436 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005437 curproxy->conn_src.tproxy_addr = *sk;
5438 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005439 }
5440 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005441#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005442 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005443#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005444#else /* no TPROXY support */
5445 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005446 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005447 err_code |= ERR_ALERT | ERR_FATAL;
5448 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005449#endif
5450 cur_arg += 2;
5451 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005452 }
5453
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005454 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5455#ifdef SO_BINDTODEVICE
5456 if (!*args[cur_arg + 1]) {
5457 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5458 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005459 err_code |= ERR_ALERT | ERR_FATAL;
5460 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005461 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005462 free(curproxy->conn_src.iface_name);
5463 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5464 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005465 global.last_checks |= LSTCHK_NETADM;
5466#else
5467 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5468 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005469 err_code |= ERR_ALERT | ERR_FATAL;
5470 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005471#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005472 cur_arg += 2;
5473 continue;
5474 }
5475 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005476 file, linenum, args[0], "interface", "usesrc");
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 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005481 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5482 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5483 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005484 err_code |= ERR_ALERT | ERR_FATAL;
5485 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005487 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005488 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005489 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5490 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005491 err_code |= ERR_ALERT | ERR_FATAL;
5492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005493 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005494
5495 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005496 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005497 args[0], args[1], args[2], (const char **)args+3);
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], "reqdel")) { /* delete request header from a 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_REMOVE, 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], "reqdeny")) { /* deny a request if a header matches this regex */
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_DENY, 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], "reqpass")) { /* pass this header without allowing or denying the request */
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_PASS, 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 }
5522 else if (!strcmp(args[0], "reqallow")) { /* allow 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_ALLOW, 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 Tarreaubaaee002006-06-26 02:48:02 +02005528 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005529 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
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_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005532 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005533 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005534 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005535 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005536 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005537 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005538 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005539 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005540 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005541 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005542
5543 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5544 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 +01005545 }
5546 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005547 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005548 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005549 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005550 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005551 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005552
5553 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5554 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 +01005555 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005556 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005557 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005558 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5559 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005560 err_code |= ERR_ALERT | ERR_FATAL;
5561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005562 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005563
5564 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005565 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005566 args[0], args[1], args[2], (const char **)args+3);
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], "reqidel")) { /* delete request header from a 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_REMOVE, 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], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
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_DENY, 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], "reqipass")) { /* pass this header without allowing or denying the request */
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_PASS, 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 }
5591 else if (!strcmp(args[0], "reqiallow")) { /* allow 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_ALLOW, 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 Tarreaubaaee002006-06-26 02:48:02 +02005597 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005598 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005599 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005600 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005601 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005602 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005603 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005604 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005606 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005607
Willy Tarreaubaaee002006-06-26 02:48:02 +02005608 if (curproxy == &defproxy) {
5609 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005610 err_code |= ERR_ALERT | ERR_FATAL;
5611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005612 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005613 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005614 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615
Willy Tarreaubaaee002006-06-26 02:48:02 +02005616 if (*(args[1]) == 0) {
5617 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005618 err_code |= ERR_ALERT | ERR_FATAL;
5619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005620 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005621
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005622 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005623 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5624 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5625 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005626 err_code |= ERR_ALERT | ERR_FATAL;
5627 goto out;
5628 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005629 err_code |= warnif_cond_conflicts(cond,
5630 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5631 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005632 }
5633 else if (*args[2]) {
5634 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5635 file, linenum, args[0], args[2]);
5636 err_code |= ERR_ALERT | ERR_FATAL;
5637 goto out;
5638 }
5639
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005640 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005641 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005642 wl->s = strdup(args[1]);
5643 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005644 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005645 }
5646 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005647 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005648 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5649 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005650 err_code |= ERR_ALERT | ERR_FATAL;
5651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005652 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005653
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_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005656 args[0], args[1], args[2], (const char **)args+3);
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], "rspdel")) { /* delete 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_REMOVE, 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], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005668 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005669 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005670 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005671 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005673 }
5674 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005675 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005676 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5677 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005678 err_code |= ERR_ALERT | ERR_FATAL;
5679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005680 }
5681
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_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005684 args[0], args[1], args[2], (const char **)args+3);
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], "rspidel")) { /* delete 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_REMOVE, 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], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005696 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005697 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005698 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005699 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005701 }
5702 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005703 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005704
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705 if (curproxy == &defproxy) {
5706 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005707 err_code |= ERR_ALERT | ERR_FATAL;
5708 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005709 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005710 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005711 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005712
Willy Tarreaubaaee002006-06-26 02:48:02 +02005713 if (*(args[1]) == 0) {
5714 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005715 err_code |= ERR_ALERT | ERR_FATAL;
5716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005717 }
5718
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005719 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005720 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5721 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5722 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005723 err_code |= ERR_ALERT | ERR_FATAL;
5724 goto out;
5725 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005726 err_code |= warnif_cond_conflicts(cond,
5727 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5728 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005729 }
5730 else if (*args[2]) {
5731 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5732 file, linenum, args[0], args[2]);
5733 err_code |= ERR_ALERT | ERR_FATAL;
5734 goto out;
5735 }
5736
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005737 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005738 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005739 wl->s = strdup(args[1]);
5740 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005741 }
5742 else if (!strcmp(args[0], "errorloc") ||
5743 !strcmp(args[0], "errorloc302") ||
5744 !strcmp(args[0], "errorloc303")) { /* error location */
5745 int errnum, errlen;
5746 char *err;
5747
Willy Tarreau977b8e42006-12-29 14:19:17 +01005748 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005749 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005750
Willy Tarreaubaaee002006-06-26 02:48:02 +02005751 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005752 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005753 err_code |= ERR_ALERT | ERR_FATAL;
5754 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755 }
5756
5757 errnum = atol(args[1]);
5758 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005759 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5760 err = malloc(errlen);
5761 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005762 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005763 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5764 err = malloc(errlen);
5765 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005766 }
5767
Willy Tarreau0f772532006-12-23 20:51:41 +01005768 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5769 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005770 chunk_destroy(&curproxy->errmsg[rc]);
5771 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005772 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005773 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005774 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005775
5776 if (rc >= HTTP_ERR_SIZE) {
5777 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5778 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005779 free(err);
5780 }
5781 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005782 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5783 int errnum, errlen, fd;
5784 char *err;
5785 struct stat stat;
5786
5787 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005788 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005789
5790 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005791 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005792 err_code |= ERR_ALERT | ERR_FATAL;
5793 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005794 }
5795
5796 fd = open(args[2], O_RDONLY);
5797 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5798 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5799 file, linenum, args[2], args[1]);
5800 if (fd >= 0)
5801 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005802 err_code |= ERR_ALERT | ERR_FATAL;
5803 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005804 }
5805
Willy Tarreau27a674e2009-08-17 07:23:33 +02005806 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005807 errlen = stat.st_size;
5808 } else {
5809 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005810 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005811 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005812 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005813 }
5814
5815 err = malloc(errlen); /* malloc() must succeed during parsing */
5816 errnum = read(fd, err, errlen);
5817 if (errnum != errlen) {
5818 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5819 file, linenum, args[2], args[1]);
5820 close(fd);
5821 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005822 err_code |= ERR_ALERT | ERR_FATAL;
5823 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005824 }
5825 close(fd);
5826
5827 errnum = atol(args[1]);
5828 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5829 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005830 chunk_destroy(&curproxy->errmsg[rc]);
5831 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005832 break;
5833 }
5834 }
5835
5836 if (rc >= HTTP_ERR_SIZE) {
5837 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5838 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005839 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005840 free(err);
5841 }
5842 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005843 else if (!strcmp(args[0], "compression")) {
5844 struct comp *comp;
5845 if (curproxy->comp == NULL) {
5846 comp = calloc(1, sizeof(struct comp));
5847 curproxy->comp = comp;
5848 } else {
5849 comp = curproxy->comp;
5850 }
5851
5852 if (!strcmp(args[1], "algo")) {
5853 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005854 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005855
William Lallemand82fe75c2012-10-23 10:25:10 +02005856 cur_arg = 2;
5857 if (!*args[cur_arg]) {
5858 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5859 file, linenum, args[0]);
5860 err_code |= ERR_ALERT | ERR_FATAL;
5861 goto out;
5862 }
5863 while (*(args[cur_arg])) {
5864 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5865 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5866 file, linenum, args[0], args[cur_arg]);
5867 err_code |= ERR_ALERT | ERR_FATAL;
5868 goto out;
5869 }
William Lallemand552df672012-11-07 13:21:47 +01005870 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5871 curproxy->comp->algos->end(&ctx);
5872 } else {
5873 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5874 file, linenum, args[0], args[cur_arg]);
5875 err_code |= ERR_ALERT | ERR_FATAL;
5876 goto out;
5877 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005878 cur_arg ++;
5879 continue;
5880 }
5881 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005882 else if (!strcmp(args[1], "offload")) {
5883 comp->offload = 1;
5884 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005885 else if (!strcmp(args[1], "type")) {
5886 int cur_arg;
5887 cur_arg = 2;
5888 if (!*args[cur_arg]) {
5889 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5890 file, linenum, args[0]);
5891 err_code |= ERR_ALERT | ERR_FATAL;
5892 goto out;
5893 }
5894 while (*(args[cur_arg])) {
5895 comp_append_type(comp, args[cur_arg]);
5896 cur_arg ++;
5897 continue;
5898 }
5899 }
5900 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005901 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005902 file, linenum, args[0]);
5903 err_code |= ERR_ALERT | ERR_FATAL;
5904 goto out;
5905 }
5906 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005907 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005908 struct cfg_kw_list *kwl;
5909 int index;
5910
5911 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5912 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5913 if (kwl->kw[index].section != CFG_LISTEN)
5914 continue;
5915 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5916 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005917 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005918 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005919 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005920 err_code |= ERR_ALERT | ERR_FATAL;
5921 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005922 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005923 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005924 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005925 err_code |= ERR_WARN;
5926 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005927 }
Willy Tarreau93893792009-07-23 13:19:11 +02005928 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005929 }
5930 }
5931 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005932
Willy Tarreau6daf3432008-01-22 16:44:08 +01005933 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005934 err_code |= ERR_ALERT | ERR_FATAL;
5935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005936 }
Willy Tarreau93893792009-07-23 13:19:11 +02005937 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005938 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005939 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005940}
5941
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005942int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005943cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
5944{
5945#ifdef CONFIG_HAP_NS
5946 const char *err;
5947 const char *item = args[0];
5948
5949 if (!strcmp(item, "namespace_list")) {
5950 return 0;
5951 }
5952 else if (!strcmp(item, "namespace")) {
5953 size_t idx = 1;
5954 const char *current;
5955 while (*(current = args[idx++])) {
5956 err = invalid_char(current);
5957 if (err) {
5958 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5959 file, linenum, *err, item, current);
5960 return ERR_ALERT | ERR_FATAL;
5961 }
5962
5963 if (netns_store_lookup(current, strlen(current))) {
5964 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
5965 file, linenum, current);
5966 return ERR_ALERT | ERR_FATAL;
5967 }
5968 if (!netns_store_insert(current)) {
5969 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
5970 file, linenum, current);
5971 return ERR_ALERT | ERR_FATAL;
5972 }
5973 }
5974 }
5975
5976 return 0;
5977#else
5978 Alert("parsing [%s:%d]: namespace support is not compiled in.",
5979 file, linenum);
5980 return ERR_ALERT | ERR_FATAL;
5981#endif
5982}
5983
5984int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005985cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5986{
5987
5988 int err_code = 0;
5989 const char *err;
5990
5991 if (!strcmp(args[0], "userlist")) { /* new userlist */
5992 struct userlist *newul;
5993
5994 if (!*args[1]) {
5995 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5996 file, linenum, args[0]);
5997 err_code |= ERR_ALERT | ERR_FATAL;
5998 goto out;
5999 }
6000
6001 err = invalid_char(args[1]);
6002 if (err) {
6003 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6004 file, linenum, *err, args[0], args[1]);
6005 err_code |= ERR_ALERT | ERR_FATAL;
6006 goto out;
6007 }
6008
6009 for (newul = userlist; newul; newul = newul->next)
6010 if (!strcmp(newul->name, args[1])) {
6011 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6012 file, linenum, args[1]);
6013 err_code |= ERR_WARN;
6014 goto out;
6015 }
6016
6017 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6018 if (!newul) {
6019 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6020 err_code |= ERR_ALERT | ERR_ABORT;
6021 goto out;
6022 }
6023
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006024 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006025 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006026 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6027 err_code |= ERR_ALERT | ERR_ABORT;
6028 goto out;
6029 }
6030
6031 newul->next = userlist;
6032 userlist = newul;
6033
6034 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006035 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006036 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006037 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006038
6039 if (!*args[1]) {
6040 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6041 file, linenum, args[0]);
6042 err_code |= ERR_ALERT | ERR_FATAL;
6043 goto out;
6044 }
6045
6046 err = invalid_char(args[1]);
6047 if (err) {
6048 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6049 file, linenum, *err, args[0], args[1]);
6050 err_code |= ERR_ALERT | ERR_FATAL;
6051 goto out;
6052 }
6053
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006054 for (ag = userlist->groups; ag; ag = ag->next)
6055 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006056 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6057 file, linenum, args[1], userlist->name);
6058 err_code |= ERR_ALERT;
6059 goto out;
6060 }
6061
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006062 ag = calloc(1, sizeof(*ag));
6063 if (!ag) {
6064 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6065 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006066 goto out;
6067 }
6068
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006069 ag->name = strdup(args[1]);
6070 if (!ag) {
6071 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6072 err_code |= ERR_ALERT | ERR_ABORT;
6073 goto out;
6074 }
6075
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006076 cur_arg = 2;
6077
6078 while (*args[cur_arg]) {
6079 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006080 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006081 cur_arg += 2;
6082 continue;
6083 } else {
6084 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6085 file, linenum, args[0]);
6086 err_code |= ERR_ALERT | ERR_FATAL;
6087 goto out;
6088 }
6089 }
6090
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006091 ag->next = userlist->groups;
6092 userlist->groups = ag;
6093
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006094 } else if (!strcmp(args[0], "user")) { /* new user */
6095 struct auth_users *newuser;
6096 int cur_arg;
6097
6098 if (!*args[1]) {
6099 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6100 file, linenum, args[0]);
6101 err_code |= ERR_ALERT | ERR_FATAL;
6102 goto out;
6103 }
6104
6105 for (newuser = userlist->users; newuser; newuser = newuser->next)
6106 if (!strcmp(newuser->user, args[1])) {
6107 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6108 file, linenum, args[1], userlist->name);
6109 err_code |= ERR_ALERT;
6110 goto out;
6111 }
6112
6113 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6114 if (!newuser) {
6115 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6116 err_code |= ERR_ALERT | ERR_ABORT;
6117 goto out;
6118 }
6119
6120 newuser->user = strdup(args[1]);
6121
6122 newuser->next = userlist->users;
6123 userlist->users = newuser;
6124
6125 cur_arg = 2;
6126
6127 while (*args[cur_arg]) {
6128 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006129#ifdef CONFIG_HAP_CRYPT
6130 if (!crypt("", args[cur_arg + 1])) {
6131 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6132 file, linenum, newuser->user);
6133 err_code |= ERR_ALERT | ERR_FATAL;
6134 goto out;
6135 }
6136#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006137 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6138 file, linenum);
6139 err_code |= ERR_ALERT;
6140#endif
6141 newuser->pass = strdup(args[cur_arg + 1]);
6142 cur_arg += 2;
6143 continue;
6144 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6145 newuser->pass = strdup(args[cur_arg + 1]);
6146 newuser->flags |= AU_O_INSECURE;
6147 cur_arg += 2;
6148 continue;
6149 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006150 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006151 cur_arg += 2;
6152 continue;
6153 } else {
6154 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6155 file, linenum, args[0]);
6156 err_code |= ERR_ALERT | ERR_FATAL;
6157 goto out;
6158 }
6159 }
6160 } else {
6161 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6162 err_code |= ERR_ALERT | ERR_FATAL;
6163 }
6164
6165out:
6166 return err_code;
6167}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006168
6169/*
6170 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006171 * Returns the error code, 0 if OK, or any combination of :
6172 * - ERR_ABORT: must abort ASAP
6173 * - ERR_FATAL: we can continue parsing but not start the service
6174 * - ERR_WARN: a warning has been emitted
6175 * - ERR_ALERT: an alert has been emitted
6176 * Only the two first ones can stop processing, the two others are just
6177 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006178 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006179int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006180{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006181 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006182 FILE *f;
6183 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006184 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006185 struct cfg_section *cs = NULL;
6186 struct cfg_section *ics;
6187
6188 /* Register internal sections */
6189 if (!cfg_register_section("listen", cfg_parse_listen) ||
6190 !cfg_register_section("frontend", cfg_parse_listen) ||
6191 !cfg_register_section("backend", cfg_parse_listen) ||
6192 !cfg_register_section("ruleset", cfg_parse_listen) ||
6193 !cfg_register_section("defaults", cfg_parse_listen) ||
6194 !cfg_register_section("global", cfg_parse_global) ||
6195 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006196 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006197 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006198 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006199 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006200
Willy Tarreaubaaee002006-06-26 02:48:02 +02006201 if ((f=fopen(file,"r")) == NULL)
6202 return -1;
6203
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006204 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006205 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006206 char *end;
6207 char *args[MAX_LINE_ARGS + 1];
6208 char *line = thisline;
6209
Willy Tarreaubaaee002006-06-26 02:48:02 +02006210 linenum++;
6211
6212 end = line + strlen(line);
6213
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006214 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6215 /* Check if we reached the limit and the last char is not \n.
6216 * Watch out for the last line without the terminating '\n'!
6217 */
6218 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006219 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006220 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006221 }
6222
Willy Tarreaubaaee002006-06-26 02:48:02 +02006223 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006224 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006225 line++;
6226
6227 arg = 0;
6228 args[arg] = line;
6229
6230 while (*line && arg < MAX_LINE_ARGS) {
6231 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6232 * C equivalent value. Other combinations left unchanged (eg: \1).
6233 */
6234 if (*line == '\\') {
6235 int skip = 0;
6236 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6237 *line = line[1];
6238 skip = 1;
6239 }
6240 else if (line[1] == 'r') {
6241 *line = '\r';
6242 skip = 1;
6243 }
6244 else if (line[1] == 'n') {
6245 *line = '\n';
6246 skip = 1;
6247 }
6248 else if (line[1] == 't') {
6249 *line = '\t';
6250 skip = 1;
6251 }
6252 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006253 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006254 unsigned char hex1, hex2;
6255 hex1 = toupper(line[2]) - '0';
6256 hex2 = toupper(line[3]) - '0';
6257 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6258 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6259 *line = (hex1<<4) + hex2;
6260 skip = 3;
6261 }
6262 else {
6263 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006264 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006265 }
6266 }
6267 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006268 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006269 end -= skip;
6270 }
6271 line++;
6272 }
6273 else if (*line == '#' || *line == '\n' || *line == '\r') {
6274 /* end of string, end of loop */
6275 *line = 0;
6276 break;
6277 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006278 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006279 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006280 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006281 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006282 line++;
6283 args[++arg] = line;
6284 }
6285 else {
6286 line++;
6287 }
6288 }
6289
6290 /* empty line */
6291 if (!**args)
6292 continue;
6293
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006294 if (*line) {
6295 /* we had to stop due to too many args.
6296 * Let's terminate the string, print the offending part then cut the
6297 * last arg.
6298 */
6299 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6300 line++;
6301 *line = '\0';
6302
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006303 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006304 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006305 err_code |= ERR_ALERT | ERR_FATAL;
6306 args[arg] = line;
6307 }
6308
Willy Tarreau540abe42007-05-02 20:50:16 +02006309 /* zero out remaining args and ensure that at least one entry
6310 * is zeroed out.
6311 */
6312 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006313 args[arg] = line;
6314 }
6315
Willy Tarreau3842f002009-06-14 11:39:52 +02006316 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006317 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006318 char *tmp;
6319
Willy Tarreau3842f002009-06-14 11:39:52 +02006320 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006321 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006322 for (arg=0; *args[arg+1]; arg++)
6323 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006324 *tmp = '\0'; // fix the next arg to \0
6325 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006326 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006327 else if (!strcmp(args[0], "default")) {
6328 kwm = KWM_DEF;
6329 for (arg=0; *args[arg+1]; arg++)
6330 args[arg] = args[arg+1]; // shift args after inversion
6331 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006332
William Lallemand0f99e342011-10-12 17:50:54 +02006333 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6334 strcmp(args[0], "log") != 0) {
6335 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006336 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006337 }
6338
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006339 /* detect section start */
6340 list_for_each_entry(ics, &sections, list) {
6341 if (strcmp(args[0], ics->section_name) == 0) {
6342 cursection = ics->section_name;
6343 cs = ics;
6344 break;
6345 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006346 }
6347
Willy Tarreaubaaee002006-06-26 02:48:02 +02006348 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006349 if (cs)
6350 err_code |= cs->section_parser(file, linenum, args, kwm);
6351 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006352 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006353 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006354 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006355
6356 if (err_code & ERR_ABORT)
6357 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006358 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006359 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006360 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006361 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006362}
6363
Willy Tarreau64ab6072014-09-16 12:17:36 +02006364/* This function propagates processes from frontend <from> to backend <to> so
6365 * that it is always guaranteed that a backend pointed to by a frontend is
6366 * bound to all of its processes. After that, if the target is a "listen"
6367 * instance, the function recursively descends the target's own targets along
6368 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6369 * checked first to ensure that <to> is already bound to all processes of
6370 * <from>, there is no risk of looping and we ensure to follow the shortest
6371 * path to the destination.
6372 *
6373 * It is possible to set <to> to NULL for the first call so that the function
6374 * takes care of visiting the initial frontend in <from>.
6375 *
6376 * It is important to note that the function relies on the fact that all names
6377 * have already been resolved.
6378 */
6379void propagate_processes(struct proxy *from, struct proxy *to)
6380{
6381 struct switching_rule *rule;
6382 struct hdr_exp *exp;
6383
6384 if (to) {
6385 /* check whether we need to go down */
6386 if (from->bind_proc &&
6387 (from->bind_proc & to->bind_proc) == from->bind_proc)
6388 return;
6389
6390 if (!from->bind_proc && !to->bind_proc)
6391 return;
6392
6393 to->bind_proc = from->bind_proc ?
6394 (to->bind_proc | from->bind_proc) : 0;
6395
6396 /* now propagate down */
6397 from = to;
6398 }
6399
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006400 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006401 return;
6402
Willy Tarreauf6b70012014-12-18 14:00:43 +01006403 if (from->state == PR_STSTOPPED)
6404 return;
6405
Willy Tarreau64ab6072014-09-16 12:17:36 +02006406 /* default_backend */
6407 if (from->defbe.be)
6408 propagate_processes(from, from->defbe.be);
6409
6410 /* use_backend */
6411 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006412 if (rule->dynamic)
6413 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006414 to = rule->be.backend;
6415 propagate_processes(from, to);
6416 }
6417
6418 /* reqsetbe */
6419 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6420 if (exp->action != ACT_SETBE)
6421 continue;
6422 to = (struct proxy *)exp->replace;
6423 propagate_processes(from, to);
6424 }
6425}
6426
Willy Tarreaubb925012009-07-23 13:36:36 +02006427/*
6428 * Returns the error code, 0 if OK, or any combination of :
6429 * - ERR_ABORT: must abort ASAP
6430 * - ERR_FATAL: we can continue parsing but not start the service
6431 * - ERR_WARN: a warning has been emitted
6432 * - ERR_ALERT: an alert has been emitted
6433 * Only the two first ones can stop processing, the two others are just
6434 * indicators.
6435 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006436int check_config_validity()
6437{
6438 int cfgerr = 0;
6439 struct proxy *curproxy = NULL;
6440 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006441 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006442 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006443 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006444
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006445 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006446 /*
6447 * Now, check for the integrity of all that we have collected.
6448 */
6449
6450 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006451 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006452
Willy Tarreau193b8c62012-11-22 00:17:38 +01006453 if (!global.tune.max_http_hdr)
6454 global.tune.max_http_hdr = MAX_HTTP_HDR;
6455
6456 if (!global.tune.cookie_len)
6457 global.tune.cookie_len = CAPTURE_LEN;
6458
6459 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6460
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006461 /* Post initialisation of the users and groups lists. */
6462 err_code = userlist_postinit();
6463 if (err_code != ERR_NONE)
6464 goto out;
6465
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006466 /* first, we will invert the proxy list order */
6467 curproxy = NULL;
6468 while (proxy) {
6469 struct proxy *next;
6470
6471 next = proxy->next;
6472 proxy->next = curproxy;
6473 curproxy = proxy;
6474 if (!next)
6475 break;
6476 proxy = next;
6477 }
6478
Willy Tarreau419ead82014-09-16 13:41:21 +02006479 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006480 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006481 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006482 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006483 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006484 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006485 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006486 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006487
Willy Tarreau050536d2012-10-04 08:47:34 +02006488 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006489 /* proxy ID not set, use automatic numbering with first
6490 * spare entry starting with next_pxid.
6491 */
6492 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6493 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6494 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006495 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006496 next_pxid++;
6497
Willy Tarreau55ea7572007-06-17 19:56:27 +02006498
Willy Tarreaubaaee002006-06-26 02:48:02 +02006499 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006500 /* ensure we don't keep listeners uselessly bound */
6501 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02006502 free((void *)curproxy->table.peers.name);
6503 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006504 continue;
6505 }
6506
Willy Tarreau102df612014-05-07 23:56:38 +02006507 /* Check multi-process mode compatibility for the current proxy */
6508
6509 if (curproxy->bind_proc) {
6510 /* an explicit bind-process was specified, let's check how many
6511 * processes remain.
6512 */
6513 nbproc = popcount(curproxy->bind_proc);
6514
6515 curproxy->bind_proc &= nbits(global.nbproc);
6516 if (!curproxy->bind_proc && nbproc == 1) {
6517 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);
6518 curproxy->bind_proc = 1;
6519 }
6520 else if (!curproxy->bind_proc && nbproc > 1) {
6521 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);
6522 curproxy->bind_proc = 0;
6523 }
6524 }
6525
Willy Tarreau3d209582014-05-09 17:06:11 +02006526 /* check and reduce the bind-proc of each listener */
6527 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6528 unsigned long mask;
6529
6530 if (!bind_conf->bind_proc)
6531 continue;
6532
6533 mask = nbits(global.nbproc);
6534 if (curproxy->bind_proc)
6535 mask &= curproxy->bind_proc;
6536 /* mask cannot be null here thanks to the previous checks */
6537
6538 nbproc = popcount(bind_conf->bind_proc);
6539 bind_conf->bind_proc &= mask;
6540
6541 if (!bind_conf->bind_proc && nbproc == 1) {
6542 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",
6543 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6544 bind_conf->bind_proc = mask & ~(mask - 1);
6545 }
6546 else if (!bind_conf->bind_proc && nbproc > 1) {
6547 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",
6548 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6549 bind_conf->bind_proc = 0;
6550 }
6551 }
6552
Willy Tarreau102df612014-05-07 23:56:38 +02006553 if (global.nbproc > 1 && curproxy->table.peers.name) {
6554 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6555 curproxy->id);
6556 cfgerr++;
6557 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006558
Willy Tarreauff01a212009-03-15 13:46:16 +01006559 switch (curproxy->mode) {
6560 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006561 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006562 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006563 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6564 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006565 cfgerr++;
6566 }
6567
6568 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006569 Warning("config : servers will be ignored for %s '%s'.\n",
6570 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006571 break;
6572
6573 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006574 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006575 break;
6576
6577 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006578 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006579 break;
6580 }
6581
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006582 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006583 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006584 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006585 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6586 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006587 cfgerr++;
6588 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006589#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006590 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006591 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6592 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006593 cfgerr++;
6594 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006595#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006596 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006597 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6598 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006599 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006600 }
6601 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006602 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006603 /* If no LB algo is set in a backend, and we're not in
6604 * transparent mode, dispatch mode nor proxy mode, we
6605 * want to use balance roundrobin by default.
6606 */
6607 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6608 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006609 }
6610 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006611
Willy Tarreau1620ec32011-08-06 17:05:02 +02006612 if (curproxy->options & PR_O_DISPATCH)
6613 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6614 else if (curproxy->options & PR_O_HTTP_PROXY)
6615 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6616 else if (curproxy->options & PR_O_TRANSP)
6617 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006618
Willy Tarreau1620ec32011-08-06 17:05:02 +02006619 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6620 if (curproxy->options & PR_O_DISABLE404) {
6621 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6622 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6623 err_code |= ERR_WARN;
6624 curproxy->options &= ~PR_O_DISABLE404;
6625 }
6626 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6627 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6628 "send-state", proxy_type_str(curproxy), curproxy->id);
6629 err_code |= ERR_WARN;
6630 curproxy->options &= ~PR_O2_CHK_SNDST;
6631 }
Willy Tarreauef781042010-01-27 11:53:01 +01006632 }
6633
Simon Horman98637e52014-06-20 12:30:16 +09006634 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6635 if (!global.external_check) {
6636 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6637 curproxy->id, "option external-check");
6638 cfgerr++;
6639 }
6640 if (!curproxy->check_command) {
6641 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6642 curproxy->id, "option external-check");
6643 cfgerr++;
6644 }
6645 }
6646
Simon Horman64e34162015-02-06 11:11:57 +09006647 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006648 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
6649 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09006650 "'email-alert from', 'email-alert level' 'email-alert mailer', "
6651 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006652 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
6653 "to be present).\n",
6654 proxy_type_str(curproxy), curproxy->id);
6655 err_code |= ERR_WARN;
6656 free_email_alert(curproxy);
6657 }
6658 if (!curproxy->email_alert.myhostname)
6659 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09006660 }
6661
Simon Horman98637e52014-06-20 12:30:16 +09006662 if (curproxy->check_command) {
6663 int clear = 0;
6664 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6665 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6666 "external-check command", proxy_type_str(curproxy), curproxy->id);
6667 err_code |= ERR_WARN;
6668 clear = 1;
6669 }
6670 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6671 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6672 curproxy->id, "external-check command");
6673 cfgerr++;
6674 }
6675 if (clear) {
6676 free(curproxy->check_command);
6677 curproxy->check_command = NULL;
6678 }
6679 }
6680
6681 if (curproxy->check_path) {
6682 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6683 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6684 "external-check path", proxy_type_str(curproxy), curproxy->id);
6685 err_code |= ERR_WARN;
6686 free(curproxy->check_path);
6687 curproxy->check_path = NULL;
6688 }
6689 }
6690
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006691 /* if a default backend was specified, let's find it */
6692 if (curproxy->defbe.name) {
6693 struct proxy *target;
6694
Alex Williams96532db2009-11-01 21:27:13 -05006695 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006696 if (!target) {
6697 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6698 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006699 cfgerr++;
6700 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006701 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6702 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006703 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006704 } else {
6705 free(curproxy->defbe.name);
6706 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006707
6708 /* Emit a warning if this proxy also has some servers */
6709 if (curproxy->srv) {
6710 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6711 curproxy->id);
6712 err_code |= ERR_WARN;
6713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006714 }
6715 }
6716
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006717 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006718 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6719 /* map jump target for ACT_SETBE in req_rep chain */
6720 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006721 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006722 struct proxy *target;
6723
Willy Tarreaua496b602006-12-17 23:15:24 +01006724 if (exp->action != ACT_SETBE)
6725 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006726
Alex Williams96532db2009-11-01 21:27:13 -05006727 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006728 if (!target) {
6729 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6730 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006731 cfgerr++;
6732 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006733 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6734 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006735 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006736 } else {
6737 free((void *)exp->replace);
6738 exp->replace = (const char *)target;
6739 }
6740 }
6741 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006742
6743 /* find the target proxy for 'use_backend' rules */
6744 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006745 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006746 struct logformat_node *node;
6747 char *pxname;
6748
6749 /* Try to parse the string as a log format expression. If the result
6750 * of the parsing is only one entry containing a simple string, then
6751 * it's a standard string corresponding to a static rule, thus the
6752 * parsing is cancelled and be.name is restored to be resolved.
6753 */
6754 pxname = rule->be.name;
6755 LIST_INIT(&rule->be.expr);
6756 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6757 curproxy->conf.args.file, curproxy->conf.args.line);
6758 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6759
6760 if (!LIST_ISEMPTY(&rule->be.expr)) {
6761 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6762 rule->dynamic = 1;
6763 free(pxname);
6764 continue;
6765 }
6766 /* simple string: free the expression and fall back to static rule */
6767 free(node->arg);
6768 free(node);
6769 }
6770
6771 rule->dynamic = 0;
6772 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006773
Alex Williams96532db2009-11-01 21:27:13 -05006774 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006775
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006776 if (!target) {
6777 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6778 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006779 cfgerr++;
6780 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006781 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6782 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006783 cfgerr++;
6784 } else {
6785 free((void *)rule->be.name);
6786 rule->be.backend = target;
6787 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006788 }
6789
Willy Tarreau64ab6072014-09-16 12:17:36 +02006790 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006791 list_for_each_entry(srule, &curproxy->server_rules, list) {
6792 struct server *target = findserver(curproxy, srule->srv.name);
6793
6794 if (!target) {
6795 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6796 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6797 cfgerr++;
6798 continue;
6799 }
6800 free((void *)srule->srv.name);
6801 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006802 }
6803
Emeric Brunb982a3d2010-01-04 15:45:53 +01006804 /* find the target table for 'stick' rules */
6805 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6806 struct proxy *target;
6807
Emeric Brun1d33b292010-01-04 15:47:17 +01006808 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6809 if (mrule->flags & STK_IS_STORE)
6810 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6811
Emeric Brunb982a3d2010-01-04 15:45:53 +01006812 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006813 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006814 else
6815 target = curproxy;
6816
6817 if (!target) {
6818 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6819 curproxy->id, mrule->table.name);
6820 cfgerr++;
6821 }
6822 else if (target->table.size == 0) {
6823 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6824 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6825 cfgerr++;
6826 }
Willy Tarreau12785782012-04-27 21:37:17 +02006827 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6828 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006829 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6830 cfgerr++;
6831 }
6832 else {
6833 free((void *)mrule->table.name);
6834 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006835 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006836 }
6837 }
6838
6839 /* find the target table for 'store response' rules */
6840 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6841 struct proxy *target;
6842
Emeric Brun1d33b292010-01-04 15:47:17 +01006843 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6844
Emeric Brunb982a3d2010-01-04 15:45:53 +01006845 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006846 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006847 else
6848 target = curproxy;
6849
6850 if (!target) {
6851 Alert("Proxy '%s': unable to find store table '%s'.\n",
6852 curproxy->id, mrule->table.name);
6853 cfgerr++;
6854 }
6855 else if (target->table.size == 0) {
6856 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6857 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6858 cfgerr++;
6859 }
Willy Tarreau12785782012-04-27 21:37:17 +02006860 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6861 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006862 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6863 cfgerr++;
6864 }
6865 else {
6866 free((void *)mrule->table.name);
6867 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006868 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006869 }
6870 }
6871
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006872 /* find the target table for 'tcp-request' layer 4 rules */
6873 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6874 struct proxy *target;
6875
Willy Tarreaub4c84932013-07-23 19:15:30 +02006876 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006877 continue;
6878
6879 if (trule->act_prm.trk_ctr.table.n)
6880 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6881 else
6882 target = curproxy;
6883
6884 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006885 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6886 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006887 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006888 cfgerr++;
6889 }
6890 else if (target->table.size == 0) {
6891 Alert("Proxy '%s': table '%s' used but not configured.\n",
6892 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6893 cfgerr++;
6894 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006895 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6896 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6897 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 +01006898 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006899 cfgerr++;
6900 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006901 else {
6902 free(trule->act_prm.trk_ctr.table.n);
6903 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006904 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006905 * to pass a list of counters to track and allocate them right here using
6906 * stktable_alloc_data_type().
6907 */
6908 }
6909 }
6910
Willy Tarreaud1f96522010-08-03 19:34:32 +02006911 /* find the target table for 'tcp-request' layer 6 rules */
6912 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6913 struct proxy *target;
6914
Willy Tarreaub4c84932013-07-23 19:15:30 +02006915 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006916 continue;
6917
6918 if (trule->act_prm.trk_ctr.table.n)
6919 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6920 else
6921 target = curproxy;
6922
6923 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006924 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6925 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006926 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006927 cfgerr++;
6928 }
6929 else if (target->table.size == 0) {
6930 Alert("Proxy '%s': table '%s' used but not configured.\n",
6931 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6932 cfgerr++;
6933 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006934 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6935 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6936 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 +01006937 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006938 cfgerr++;
6939 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006940 else {
6941 free(trule->act_prm.trk_ctr.table.n);
6942 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006943 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006944 * to pass a list of counters to track and allocate them right here using
6945 * stktable_alloc_data_type().
6946 */
6947 }
6948 }
6949
Willy Tarreau09448f72014-06-25 18:12:15 +02006950 /* find the target table for 'http-request' layer 7 rules */
6951 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6952 struct proxy *target;
6953
6954 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6955 continue;
6956
6957 if (hrqrule->act_prm.trk_ctr.table.n)
6958 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6959 else
6960 target = curproxy;
6961
6962 if (!target) {
6963 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6964 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6965 http_req_trk_idx(hrqrule->action));
6966 cfgerr++;
6967 }
6968 else if (target->table.size == 0) {
6969 Alert("Proxy '%s': table '%s' used but not configured.\n",
6970 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6971 cfgerr++;
6972 }
6973 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6974 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6975 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6976 http_req_trk_idx(hrqrule->action));
6977 cfgerr++;
6978 }
6979 else {
6980 free(hrqrule->act_prm.trk_ctr.table.n);
6981 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6982 /* Note: if we decide to enhance the track-sc syntax, we may be able
6983 * to pass a list of counters to track and allocate them right here using
6984 * stktable_alloc_data_type().
6985 */
6986 }
6987 }
6988
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006989 /* move any "block" rules at the beginning of the http-request rules */
6990 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6991 /* insert block_rules into http_req_rules at the beginning */
6992 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6993 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6994 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6995 curproxy->http_req_rules.n = curproxy->block_rules.n;
6996 LIST_INIT(&curproxy->block_rules);
6997 }
6998
Emeric Brun32da3c42010-09-23 18:39:19 +02006999 if (curproxy->table.peers.name) {
7000 struct peers *curpeers = peers;
7001
7002 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7003 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7004 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007005 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007006 break;
7007 }
7008 }
7009
7010 if (!curpeers) {
7011 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7012 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007013 free((void *)curproxy->table.peers.name);
7014 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007015 cfgerr++;
7016 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007017 else if (curpeers->state == PR_STSTOPPED) {
7018 /* silently disable this peers section */
7019 curproxy->table.peers.p = NULL;
7020 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007021 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007022 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7023 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007024 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007025 cfgerr++;
7026 }
7027 }
7028
Simon Horman9dc49962015-01-30 11:22:59 +09007029
7030 if (curproxy->email_alert.mailers.name) {
7031 struct mailers *curmailers = mailers;
7032
7033 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7034 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7035 free(curproxy->email_alert.mailers.name);
7036 curproxy->email_alert.mailers.m = curmailers;
7037 curmailers->users++;
7038 break;
7039 }
7040 }
7041
7042 if (!curmailers) {
7043 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7044 curproxy->id, curproxy->email_alert.mailers.name);
7045 free_email_alert(curproxy);
7046 cfgerr++;
7047 }
7048 }
7049
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007050 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007051 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007052 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7053 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7054 "proxy", curproxy->id);
7055 cfgerr++;
7056 goto out_uri_auth_compat;
7057 }
7058
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007059 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007060 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007061 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007062 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007063
Willy Tarreau95fa4692010-02-01 13:05:50 +01007064 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7065 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007066
7067 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007068 uri_auth_compat_req[i++] = "realm";
7069 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7070 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007071
Willy Tarreau95fa4692010-02-01 13:05:50 +01007072 uri_auth_compat_req[i++] = "unless";
7073 uri_auth_compat_req[i++] = "{";
7074 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7075 uri_auth_compat_req[i++] = "}";
7076 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007077
Willy Tarreauff011f22011-01-06 17:51:27 +01007078 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7079 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007080 cfgerr++;
7081 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007082 }
7083
Willy Tarreauff011f22011-01-06 17:51:27 +01007084 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007085
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007086 if (curproxy->uri_auth->auth_realm) {
7087 free(curproxy->uri_auth->auth_realm);
7088 curproxy->uri_auth->auth_realm = NULL;
7089 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007090
7091 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007092 }
7093out_uri_auth_compat:
7094
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007095 /* compile the log format */
7096 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007097 if (curproxy->conf.logformat_string != default_http_log_format &&
7098 curproxy->conf.logformat_string != default_tcp_log_format &&
7099 curproxy->conf.logformat_string != clf_http_log_format)
7100 free(curproxy->conf.logformat_string);
7101 curproxy->conf.logformat_string = NULL;
7102 free(curproxy->conf.lfs_file);
7103 curproxy->conf.lfs_file = NULL;
7104 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007105 }
7106
Willy Tarreau62a61232013-04-12 18:13:46 +02007107 if (curproxy->conf.logformat_string) {
7108 curproxy->conf.args.ctx = ARGC_LOG;
7109 curproxy->conf.args.file = curproxy->conf.lfs_file;
7110 curproxy->conf.args.line = curproxy->conf.lfs_line;
7111 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007112 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_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
Willy Tarreau62a61232013-04-12 18:13:46 +02007117 if (curproxy->conf.uniqueid_format_string) {
7118 curproxy->conf.args.ctx = ARGC_UIF;
7119 curproxy->conf.args.file = curproxy->conf.uif_file;
7120 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007121 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007122 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007123 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007124 curproxy->conf.args.file = NULL;
7125 curproxy->conf.args.line = 0;
7126 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007127
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007128 /* only now we can check if some args remain unresolved.
7129 * This must be done after the users and groups resolution.
7130 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007131 cfgerr += smp_resolve_args(curproxy);
7132 if (!cfgerr)
7133 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007134
Willy Tarreau2738a142006-07-08 17:28:09 +02007135 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007136 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007137 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007138 (!curproxy->timeout.connect ||
7139 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007140 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007141 " | While not properly invalid, you will certainly encounter various problems\n"
7142 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007143 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007144 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007145 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007146 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007147
Willy Tarreau1fa31262007-12-03 00:36:16 +01007148 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7149 * We must still support older configurations, so let's find out whether those
7150 * parameters have been set or must be copied from contimeouts.
7151 */
7152 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007153 if (!curproxy->timeout.tarpit ||
7154 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007155 /* tarpit timeout not set. We search in the following order:
7156 * default.tarpit, curr.connect, default.connect.
7157 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007158 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007159 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007160 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007161 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007162 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007163 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007164 }
7165 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007166 (!curproxy->timeout.queue ||
7167 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007168 /* queue timeout not set. We search in the following order:
7169 * default.queue, curr.connect, default.connect.
7170 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007171 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007172 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007173 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007174 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007175 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007176 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007177 }
7178 }
7179
Willy Tarreau1620ec32011-08-06 17:05:02 +02007180 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007181 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7182 curproxy->check_req = (char *)malloc(curproxy->check_len);
7183 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007184 }
7185
Willy Tarreau215663d2014-06-13 18:30:23 +02007186 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7187 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7188 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7189 proxy_type_str(curproxy), curproxy->id);
7190 err_code |= ERR_WARN;
7191 }
7192
Willy Tarreau193b8c62012-11-22 00:17:38 +01007193 /* ensure that cookie capture length is not too large */
7194 if (curproxy->capture_len >= global.tune.cookie_len) {
7195 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7196 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7197 err_code |= ERR_WARN;
7198 curproxy->capture_len = global.tune.cookie_len - 1;
7199 }
7200
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007201 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007202 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007203 curproxy->req_cap_pool = create_pool("ptrcap",
7204 curproxy->nb_req_cap * sizeof(char *),
7205 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007206 }
7207
7208 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007209 curproxy->rsp_cap_pool = create_pool("ptrcap",
7210 curproxy->nb_rsp_cap * sizeof(char *),
7211 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007212 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007213
Willy Tarreaubaaee002006-06-26 02:48:02 +02007214 /* first, we will invert the servers list order */
7215 newsrv = NULL;
7216 while (curproxy->srv) {
7217 struct server *next;
7218
7219 next = curproxy->srv->next;
7220 curproxy->srv->next = newsrv;
7221 newsrv = curproxy->srv;
7222 if (!next)
7223 break;
7224 curproxy->srv = next;
7225 }
7226
Willy Tarreau17edc812014-01-03 12:14:34 +01007227 /* Check that no server name conflicts. This causes trouble in the stats.
7228 * We only emit a warning for the first conflict affecting each server,
7229 * in order to avoid combinatory explosion if all servers have the same
7230 * name. We do that only for servers which do not have an explicit ID,
7231 * because these IDs were made also for distinguishing them and we don't
7232 * want to annoy people who correctly manage them.
7233 */
7234 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7235 struct server *other_srv;
7236
7237 if (newsrv->puid)
7238 continue;
7239
7240 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7241 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7242 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7243 newsrv->conf.file, newsrv->conf.line,
7244 proxy_type_str(curproxy), curproxy->id,
7245 newsrv->id, other_srv->conf.line);
7246 break;
7247 }
7248 }
7249 }
7250
Willy Tarreaudd701652010-05-25 23:03:02 +02007251 /* assign automatic UIDs to servers which don't have one yet */
7252 next_id = 1;
7253 newsrv = curproxy->srv;
7254 while (newsrv != NULL) {
7255 if (!newsrv->puid) {
7256 /* server ID not set, use automatic numbering with first
7257 * spare entry starting with next_svid.
7258 */
7259 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7260 newsrv->conf.id.key = newsrv->puid = next_id;
7261 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7262 }
7263 next_id++;
7264 newsrv = newsrv->next;
7265 }
7266
Willy Tarreau20697042007-11-15 23:26:18 +01007267 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007268 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007269
Willy Tarreau62c3be22012-01-20 13:12:32 +01007270 /*
7271 * If this server supports a maxconn parameter, it needs a dedicated
7272 * tasks to fill the emptied slots when a connection leaves.
7273 * Also, resolve deferred tracking dependency if needed.
7274 */
7275 newsrv = curproxy->srv;
7276 while (newsrv != NULL) {
7277 if (newsrv->minconn > newsrv->maxconn) {
7278 /* Only 'minconn' was specified, or it was higher than or equal
7279 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7280 * this will avoid further useless expensive computations.
7281 */
7282 newsrv->maxconn = newsrv->minconn;
7283 } else if (newsrv->maxconn && !newsrv->minconn) {
7284 /* minconn was not specified, so we set it to maxconn */
7285 newsrv->minconn = newsrv->maxconn;
7286 }
7287
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007288#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007289 if (newsrv->use_ssl || newsrv->check.use_ssl)
7290 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007291#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007292
Willy Tarreau2f075e92013-12-03 11:11:34 +01007293 /* set the check type on the server */
7294 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7295
Willy Tarreau62c3be22012-01-20 13:12:32 +01007296 if (newsrv->trackit) {
7297 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007298 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007299 char *pname, *sname;
7300
7301 pname = newsrv->trackit;
7302 sname = strrchr(pname, '/');
7303
7304 if (sname)
7305 *sname++ = '\0';
7306 else {
7307 sname = pname;
7308 pname = NULL;
7309 }
7310
7311 if (pname) {
7312 px = findproxy(pname, PR_CAP_BE);
7313 if (!px) {
7314 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7315 proxy_type_str(curproxy), curproxy->id,
7316 newsrv->id, pname);
7317 cfgerr++;
7318 goto next_srv;
7319 }
7320 } else
7321 px = curproxy;
7322
7323 srv = findserver(px, sname);
7324 if (!srv) {
7325 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7326 proxy_type_str(curproxy), curproxy->id,
7327 newsrv->id, sname);
7328 cfgerr++;
7329 goto next_srv;
7330 }
7331
Willy Tarreau32091232014-05-16 13:52:00 +02007332 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7333 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7334 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007335 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007336 "tracking as it does not have any check nor agent enabled.\n",
7337 proxy_type_str(curproxy), curproxy->id,
7338 newsrv->id, px->id, srv->id);
7339 cfgerr++;
7340 goto next_srv;
7341 }
7342
7343 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7344
7345 if (loop) {
7346 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7347 "belongs to a tracking chain looping back to %s/%s.\n",
7348 proxy_type_str(curproxy), curproxy->id,
7349 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007350 cfgerr++;
7351 goto next_srv;
7352 }
7353
7354 if (curproxy != px &&
7355 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7356 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7357 "tracking: disable-on-404 option inconsistency.\n",
7358 proxy_type_str(curproxy), curproxy->id,
7359 newsrv->id, px->id, srv->id);
7360 cfgerr++;
7361 goto next_srv;
7362 }
7363
7364 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007365 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007366 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007367 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007368 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007369 }
7370
7371 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007372 newsrv->tracknext = srv->trackers;
7373 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007374
7375 free(newsrv->trackit);
7376 newsrv->trackit = NULL;
7377 }
7378 next_srv:
7379 newsrv = newsrv->next;
7380 }
7381
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007382 /* We have to initialize the server lookup mechanism depending
7383 * on what LB algorithm was choosen.
7384 */
7385
7386 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7387 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7388 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007389 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7390 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7391 init_server_map(curproxy);
7392 } else {
7393 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7394 fwrr_init_server_groups(curproxy);
7395 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007396 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007397
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007398 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007399 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7400 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7401 fwlc_init_server_tree(curproxy);
7402 } else {
7403 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7404 fas_init_server_tree(curproxy);
7405 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007406 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007407
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007408 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007409 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7410 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7411 chash_init_server_tree(curproxy);
7412 } else {
7413 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7414 init_server_map(curproxy);
7415 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007416 break;
7417 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007418
7419 if (curproxy->options & PR_O_LOGASAP)
7420 curproxy->to_log &= ~LW_BYTES;
7421
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007422 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007423 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007424 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7425 proxy_type_str(curproxy), curproxy->id);
7426 err_code |= ERR_WARN;
7427 }
7428
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007429 if (curproxy->mode != PR_MODE_HTTP) {
7430 int optnum;
7431
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007432 if (curproxy->uri_auth) {
7433 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7434 proxy_type_str(curproxy), curproxy->id);
7435 err_code |= ERR_WARN;
7436 curproxy->uri_auth = NULL;
7437 }
7438
Willy Tarreau87cf5142011-08-19 22:57:24 +02007439 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007440 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7441 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7442 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007443 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007444 }
7445
7446 if (curproxy->options & PR_O_ORGTO) {
7447 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7448 "originalto", proxy_type_str(curproxy), curproxy->id);
7449 err_code |= ERR_WARN;
7450 curproxy->options &= ~PR_O_ORGTO;
7451 }
7452
7453 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7454 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7455 (curproxy->cap & cfg_opts[optnum].cap) &&
7456 (curproxy->options & cfg_opts[optnum].val)) {
7457 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7458 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7459 err_code |= ERR_WARN;
7460 curproxy->options &= ~cfg_opts[optnum].val;
7461 }
7462 }
7463
7464 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7465 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7466 (curproxy->cap & cfg_opts2[optnum].cap) &&
7467 (curproxy->options2 & cfg_opts2[optnum].val)) {
7468 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7469 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7470 err_code |= ERR_WARN;
7471 curproxy->options2 &= ~cfg_opts2[optnum].val;
7472 }
7473 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007474
Pieter Baauwd551fb52013-05-08 22:49:23 +02007475#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007476 if (curproxy->conn_src.bind_hdr_occ) {
7477 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007478 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007479 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007480 err_code |= ERR_WARN;
7481 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007482#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007483 }
7484
Willy Tarreaubaaee002006-06-26 02:48:02 +02007485 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007486 * ensure that we're not cross-dressing a TCP server into HTTP.
7487 */
7488 newsrv = curproxy->srv;
7489 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007490 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007491 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7492 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007493 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007494 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007495
Willy Tarreau0cec3312011-10-31 13:49:26 +01007496 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7497 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7498 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7499 err_code |= ERR_WARN;
7500 }
7501
Willy Tarreauc93cd162014-05-13 15:54:22 +02007502 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007503 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7504 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7505 err_code |= ERR_WARN;
7506 }
7507
Pieter Baauwd551fb52013-05-08 22:49:23 +02007508#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007509 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7510 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007511 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 +01007512 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007513 err_code |= ERR_WARN;
7514 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007515#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007516 newsrv = newsrv->next;
7517 }
7518
Willy Tarreaue42bd962014-09-16 16:21:19 +02007519 /* check if we have a frontend with "tcp-request content" looking at L7
7520 * with no inspect-delay
7521 */
7522 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7523 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7524 if (trule->action == TCP_ACT_CAPTURE &&
7525 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7526 break;
7527 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7528 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7529 break;
7530 }
7531
7532 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7533 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7534 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7535 " This means that these rules will randomly find their contents. This can be fixed by"
7536 " setting the tcp-request inspect-delay.\n",
7537 proxy_type_str(curproxy), curproxy->id);
7538 err_code |= ERR_WARN;
7539 }
7540 }
7541
Willy Tarreauc1a21672009-08-16 22:37:44 +02007542 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007543 if (!curproxy->accept)
7544 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007545
Willy Tarreauc1a21672009-08-16 22:37:44 +02007546 if (curproxy->tcp_req.inspect_delay ||
7547 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007548 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007549
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007550 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007551 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007552 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007553 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007554
7555 /* both TCP and HTTP must check switching rules */
7556 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7557 }
7558
7559 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007560 if (curproxy->tcp_req.inspect_delay ||
7561 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7562 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7563
Emeric Brun97679e72010-09-23 17:56:44 +02007564 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7565 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7566
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007567 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007568 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007569 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007570 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007571
7572 /* If the backend does requires RDP cookie persistence, we have to
7573 * enable the corresponding analyser.
7574 */
7575 if (curproxy->options2 & PR_O2_RDPC_PRST)
7576 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7577 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007578 }
7579
7580 /***********************************************************/
7581 /* At this point, target names have already been resolved. */
7582 /***********************************************************/
7583
7584 /* Check multi-process mode compatibility */
7585
7586 if (global.nbproc > 1 && global.stats_fe) {
7587 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7588 unsigned long mask;
7589
7590 mask = nbits(global.nbproc);
7591 if (global.stats_fe->bind_proc)
7592 mask &= global.stats_fe->bind_proc;
7593
7594 if (bind_conf->bind_proc)
7595 mask &= bind_conf->bind_proc;
7596
7597 /* stop here if more than one process is used */
7598 if (popcount(mask) > 1)
7599 break;
7600 }
7601 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7602 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");
7603 }
7604 }
7605
7606 /* Make each frontend inherit bind-process from its listeners when not specified. */
7607 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7608 if (curproxy->bind_proc)
7609 continue;
7610
7611 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7612 unsigned long mask;
7613
7614 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7615 curproxy->bind_proc |= mask;
7616 }
7617
7618 if (!curproxy->bind_proc)
7619 curproxy->bind_proc = ~0UL;
7620 }
7621
7622 if (global.stats_fe) {
7623 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7624 unsigned long mask;
7625
7626 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7627 global.stats_fe->bind_proc |= mask;
7628 }
7629 if (!global.stats_fe->bind_proc)
7630 global.stats_fe->bind_proc = ~0UL;
7631 }
7632
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007633 /* propagate bindings from frontends to backends. Don't do it if there
7634 * are any fatal errors as we must not call it with unresolved proxies.
7635 */
7636 if (!cfgerr) {
7637 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7638 if (curproxy->cap & PR_CAP_FE)
7639 propagate_processes(curproxy, NULL);
7640 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007641 }
7642
7643 /* Bind each unbound backend to all processes when not specified. */
7644 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7645 if (curproxy->bind_proc)
7646 continue;
7647 curproxy->bind_proc = ~0UL;
7648 }
7649
7650 /*******************************************************/
7651 /* At this step, all proxies have a non-null bind_proc */
7652 /*******************************************************/
7653
7654 /* perform the final checks before creating tasks */
7655
7656 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7657 struct listener *listener;
7658 unsigned int next_id;
7659 int nbproc;
7660
7661 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007662
Emeric Brunc52962f2012-11-15 18:28:02 +01007663#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007664 /* Configure SSL for each bind line.
7665 * Note: if configuration fails at some point, the ->ctx member
7666 * remains NULL so that listeners can later detach.
7667 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007668 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007669 int alloc_ctx;
7670
Emeric Brunc52962f2012-11-15 18:28:02 +01007671 if (!bind_conf->is_ssl) {
7672 if (bind_conf->default_ctx) {
7673 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7674 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7675 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007676 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007677 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007678 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007679 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007680 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007681 cfgerr++;
7682 continue;
7683 }
7684
Emeric Brun8dc60392014-05-09 13:52:00 +02007685 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007686 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007687 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7688 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");
7689 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007690 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007691 cfgerr++;
7692 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007693 }
7694
Emeric Brunfc0421f2012-09-07 17:30:07 +02007695 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007696 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007697 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007698#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007699
Willy Tarreaue6b98942007-10-29 01:09:36 +01007700 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007701 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007702 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007703 if (!listener->luid) {
7704 /* listener ID not set, use automatic numbering with first
7705 * spare entry starting with next_luid.
7706 */
7707 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7708 listener->conf.id.key = listener->luid = next_id;
7709 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007710 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007711 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007712
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007713 /* enable separate counters */
7714 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7715 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007716 if (!listener->name)
7717 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007718 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007719
Willy Tarreaue6b98942007-10-29 01:09:36 +01007720 if (curproxy->options & PR_O_TCP_NOLING)
7721 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007722 if (!listener->maxconn)
7723 listener->maxconn = curproxy->maxconn;
7724 if (!listener->backlog)
7725 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007726 if (!listener->maxaccept)
7727 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7728
7729 /* we want to have an optimal behaviour on single process mode to
7730 * maximize the work at once, but in multi-process we want to keep
7731 * some fairness between processes, so we target half of the max
7732 * number of events to be balanced over all the processes the proxy
7733 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7734 * used to disable the limit.
7735 */
7736 if (listener->maxaccept > 0) {
7737 if (nbproc > 1)
7738 listener->maxaccept = (listener->maxaccept + 1) / 2;
7739 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7740 }
7741
Willy Tarreau9903f0e2015-04-04 18:50:31 +02007742 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02007743 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007744 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01007745 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007746
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007747 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7748 listener->options |= LI_O_TCP_RULES;
7749
Willy Tarreaude3041d2010-05-31 10:56:17 +02007750 if (curproxy->mon_mask.s_addr)
7751 listener->options |= LI_O_CHK_MONNET;
7752
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007753 /* smart accept mode is automatic in HTTP mode */
7754 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007755 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007756 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7757 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007758 }
7759
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007760 /* Release unused SSL configs */
7761 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7762 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007763 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007764#ifdef USE_OPENSSL
7765 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007766 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007767 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007768 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007769 free(bind_conf->crl_file);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007770 free(bind_conf->tls_ticket_keys);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007771#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007772 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007773
Willy Tarreau102df612014-05-07 23:56:38 +02007774 if (nbproc > 1) {
7775 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02007776 int count, maxproc = 0;
7777
7778 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7779 count = popcount(bind_conf->bind_proc);
7780 if (count > maxproc)
7781 maxproc = count;
7782 }
7783 /* backends have 0, frontends have 1 or more */
7784 if (maxproc != 1)
7785 Warning("Proxy '%s': in multi-process mode, stats will be"
7786 " limited to process assigned to the current request.\n",
7787 curproxy->id);
7788
Willy Tarreau102df612014-05-07 23:56:38 +02007789 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7790 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7791 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007792 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007793 }
Willy Tarreau102df612014-05-07 23:56:38 +02007794 if (curproxy->appsession_name) {
7795 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7796 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007797 }
Willy Tarreau102df612014-05-07 23:56:38 +02007798 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7799 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7800 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007801 }
7802 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007803
7804 /* create the task associated with the proxy */
7805 curproxy->task = task_new();
7806 if (curproxy->task) {
7807 curproxy->task->context = curproxy;
7808 curproxy->task->process = manage_proxy;
7809 /* no need to queue, it will be done automatically if some
7810 * listener gets limited.
7811 */
7812 curproxy->task->expire = TICK_ETERNITY;
7813 } else {
7814 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7815 curproxy->id);
7816 cfgerr++;
7817 }
Willy Tarreaub369a042014-09-16 13:21:03 +02007818 }
7819
Willy Tarreaufbb78422011-06-05 15:38:35 +02007820 /* automatically compute fullconn if not set. We must not do it in the
7821 * loop above because cross-references are not yet fully resolved.
7822 */
7823 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7824 /* If <fullconn> is not set, let's set it to 10% of the sum of
7825 * the possible incoming frontend's maxconns.
7826 */
7827 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7828 struct proxy *fe;
7829 int total = 0;
7830
7831 /* sum up the number of maxconns of frontends which
7832 * reference this backend at least once or which are
7833 * the same one ('listen').
7834 */
7835 for (fe = proxy; fe; fe = fe->next) {
7836 struct switching_rule *rule;
7837 struct hdr_exp *exp;
7838 int found = 0;
7839
7840 if (!(fe->cap & PR_CAP_FE))
7841 continue;
7842
7843 if (fe == curproxy) /* we're on a "listen" instance */
7844 found = 1;
7845
7846 if (fe->defbe.be == curproxy) /* "default_backend" */
7847 found = 1;
7848
7849 /* check if a "use_backend" rule matches */
7850 if (!found) {
7851 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007852 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007853 found = 1;
7854 break;
7855 }
7856 }
7857 }
7858
7859 /* check if a "reqsetbe" rule matches */
7860 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7861 if (exp->action == ACT_SETBE &&
7862 (struct proxy *)exp->replace == curproxy) {
7863 found = 1;
7864 break;
7865 }
7866 }
7867
7868 /* now we've checked all possible ways to reference a backend
7869 * from a frontend.
7870 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007871 if (!found)
7872 continue;
7873 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007874 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007875 /* we have the sum of the maxconns in <total>. We only
7876 * keep 10% of that sum to set the default fullconn, with
7877 * a hard minimum of 1 (to avoid a divide by zero).
7878 */
7879 curproxy->fullconn = (total + 9) / 10;
7880 if (!curproxy->fullconn)
7881 curproxy->fullconn = 1;
7882 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007883 }
7884
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007885 /*
7886 * Recount currently required checks.
7887 */
7888
7889 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7890 int optnum;
7891
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007892 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7893 if (curproxy->options & cfg_opts[optnum].val)
7894 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007895
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007896 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7897 if (curproxy->options2 & cfg_opts2[optnum].val)
7898 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007899 }
7900
Willy Tarreau0fca4832015-05-01 19:12:05 +02007901 /* compute the required process bindings for the peers */
7902 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
7903 if (curproxy->table.peers.p)
7904 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
7905
Willy Tarreau122541c2011-09-07 21:24:49 +02007906 if (peers) {
7907 struct peers *curpeers = peers, **last;
7908 struct peer *p, *pb;
7909
7910 /* Remove all peers sections which don't have a valid listener.
7911 * This can happen when a peers section is never referenced and
7912 * does not contain a local peer.
7913 */
7914 last = &peers;
7915 while (*last) {
7916 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007917
7918 if (curpeers->state == PR_STSTOPPED) {
7919 /* the "disabled" keyword was present */
7920 if (curpeers->peers_fe)
7921 stop_proxy(curpeers->peers_fe);
7922 curpeers->peers_fe = NULL;
7923 }
7924 else if (!curpeers->peers_fe) {
7925 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7926 curpeers->id, localpeer);
7927 }
7928 else {
Willy Tarreau122541c2011-09-07 21:24:49 +02007929 last = &curpeers->next;
7930 continue;
7931 }
7932
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007933 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02007934 p = curpeers->remote;
7935 while (p) {
7936 pb = p->next;
7937 free(p->id);
7938 free(p);
7939 p = pb;
7940 }
7941
7942 /* Destroy and unlink this curpeers section.
7943 * Note: curpeers is backed up into *last.
7944 */
7945 free(curpeers->id);
7946 curpeers = curpeers->next;
7947 free(*last);
7948 *last = curpeers;
7949 }
7950 }
7951
Willy Tarreau6866f3f2015-05-01 19:09:08 +02007952 /* initialize stick-tables on backend capable proxies. This must not
7953 * be done earlier because the data size may be discovered while parsing
7954 * other proxies.
7955 */
7956 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7957 if (curproxy->state == PR_STSTOPPED)
7958 continue;
7959
7960 if (!stktable_init(&curproxy->table)) {
7961 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7962 cfgerr++;
7963 }
7964 }
7965
Simon Horman0d16a402015-01-30 11:22:58 +09007966 if (mailers) {
7967 struct mailers *curmailers = mailers, **last;
7968 struct mailer *m, *mb;
7969
7970 /* Remove all mailers sections which don't have a valid listener.
7971 * This can happen when a mailers section is never referenced.
7972 */
7973 last = &mailers;
7974 while (*last) {
7975 curmailers = *last;
7976 if (curmailers->users) {
7977 last = &curmailers->next;
7978 continue;
7979 }
7980
7981 Warning("Removing incomplete section 'mailers %s'.\n",
7982 curmailers->id);
7983
7984 m = curmailers->mailer_list;
7985 while (m) {
7986 mb = m->next;
7987 free(m->id);
7988 free(m);
7989 m = mb;
7990 }
7991
7992 /* Destroy and unlink this curmailers section.
7993 * Note: curmailers is backed up into *last.
7994 */
7995 free(curmailers->id);
7996 curmailers = curmailers->next;
7997 free(*last);
7998 *last = curmailers;
7999 }
8000 }
8001
Willy Tarreau34eb6712011-10-24 18:15:04 +02008002 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008003 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008004 MEM_F_SHARED);
8005
Willy Tarreaubb925012009-07-23 13:36:36 +02008006 if (cfgerr > 0)
8007 err_code |= ERR_ALERT | ERR_FATAL;
8008 out:
8009 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008010}
8011
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008012/*
8013 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8014 * parsing sessions.
8015 */
8016void cfg_register_keywords(struct cfg_kw_list *kwl)
8017{
8018 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8019}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008020
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008021/*
8022 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8023 */
8024void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8025{
8026 LIST_DEL(&kwl->list);
8027 LIST_INIT(&kwl->list);
8028}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008029
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008030/* this function register new section in the haproxy configuration file.
8031 * <section_name> is the name of this new section and <section_parser>
8032 * is the called parser. If two section declaration have the same name,
8033 * only the first declared is used.
8034 */
8035int cfg_register_section(char *section_name,
8036 int (*section_parser)(const char *, int, char **, int))
8037{
8038 struct cfg_section *cs;
8039
8040 cs = calloc(1, sizeof(*cs));
8041 if (!cs) {
8042 Alert("register section '%s': out of memory.\n", section_name);
8043 return 0;
8044 }
8045
8046 cs->section_name = section_name;
8047 cs->section_parser = section_parser;
8048
8049 LIST_ADDQ(&sections, &cs->list);
8050
8051 return 1;
8052}
8053
Willy Tarreaubaaee002006-06-26 02:48:02 +02008054/*
8055 * Local variables:
8056 * c-indent-level: 8
8057 * c-basic-offset: 8
8058 * End:
8059 */