blob: 26d2f9145800539c2079b7c2cf1070999a1eaac6 [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 Tarreau9fbe18e2015-05-01 22:42:08 +0200157 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200158 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100159 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
161 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
162 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "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;
Joseph Lynch726ab712015-05-11 23:25:34 -07001619 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001620
Simon Horman66183002013-02-23 10:16:43 +09001621 defproxy.defsrv.check.inter = DEF_CHKINTR;
1622 defproxy.defsrv.check.fastinter = 0;
1623 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001624 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1625 defproxy.defsrv.agent.fastinter = 0;
1626 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001627 defproxy.defsrv.check.rise = DEF_RISETIME;
1628 defproxy.defsrv.check.fall = DEF_FALLTIME;
1629 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1630 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001631 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001632 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001633 defproxy.defsrv.maxqueue = 0;
1634 defproxy.defsrv.minconn = 0;
1635 defproxy.defsrv.maxconn = 0;
1636 defproxy.defsrv.slowstart = 0;
1637 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1638 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1639 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001640
1641 defproxy.email_alert.level = LOG_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001642}
1643
Willy Tarreauade5ec42010-01-28 19:33:49 +01001644
Willy Tarreau63af98d2014-05-18 08:11:41 +02001645/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1646 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1647 * ERR_FATAL in case of error.
1648 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001649static int create_cond_regex_rule(const char *file, int line,
1650 struct proxy *px, int dir, int action, int flags,
1651 const char *cmd, const char *reg, const char *repl,
1652 const char **cond_start)
1653{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001654 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001655 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001656 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001657 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001658 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001659 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001660 int cs;
1661 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001662
1663 if (px == &defproxy) {
1664 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001665 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001666 goto err;
1667 }
1668
1669 if (*reg == 0) {
1670 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001671 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001672 goto err;
1673 }
1674
1675 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001676 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001677
Willy Tarreau5321c422010-01-28 20:35:13 +01001678 if (cond_start &&
1679 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001680 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1681 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1682 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001683 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001684 goto err;
1685 }
1686 }
1687 else if (cond_start && **cond_start) {
1688 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1689 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001690 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001691 goto err;
1692 }
1693
Willy Tarreau63af98d2014-05-18 08:11:41 +02001694 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001695 (dir == SMP_OPT_DIR_REQ) ?
1696 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1697 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1698 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001699
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001700 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001701 if (!preg) {
1702 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001703 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001704 goto err;
1705 }
1706
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001707 cs = !(flags & REG_ICASE);
1708 cap = !(flags & REG_NOSUB);
1709 error = NULL;
1710 if (!regex_comp(reg, preg, cs, cap, &error)) {
1711 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1712 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001713 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001714 goto err;
1715 }
1716
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001717 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001718 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001719 if (repl && err) {
1720 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1721 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001722 ret_code |= ERR_ALERT | ERR_FATAL;
1723 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001724 }
1725
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001726 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001727 ret_code |= ERR_WARN;
1728
1729 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001730
Willy Tarreau63af98d2014-05-18 08:11:41 +02001731 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001732 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001733 err:
1734 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001735 free(errmsg);
1736 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001737}
1738
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001740 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001741 * Returns the error code, 0 if OK, or any combination of :
1742 * - ERR_ABORT: must abort ASAP
1743 * - ERR_FATAL: we can continue parsing but not start the service
1744 * - ERR_WARN: a warning has been emitted
1745 * - ERR_ALERT: an alert has been emitted
1746 * Only the two first ones can stop processing, the two others are just
1747 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001748 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001749int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1750{
1751 static struct peers *curpeers = NULL;
1752 struct peer *newpeer = NULL;
1753 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001754 struct bind_conf *bind_conf;
1755 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001756 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001757 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001758
1759 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001760 if (!*args[1]) {
1761 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001762 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001763 goto out;
1764 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001765
1766 err = invalid_char(args[1]);
1767 if (err) {
1768 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1769 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001770 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001771 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001772 }
1773
1774 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1775 /*
1776 * If there are two proxies with the same name only following
1777 * combinations are allowed:
1778 */
1779 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001780 Alert("Parsing [%s:%d]: peers section '%s' has the same name as another peers section declared at %s:%d.\n",
Emeric Brun32da3c42010-09-23 18:39:19 +02001781 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001782 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001783 }
1784 }
1785
1786 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1787 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1788 err_code |= ERR_ALERT | ERR_ABORT;
1789 goto out;
1790 }
1791
1792 curpeers->next = peers;
1793 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001794 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001795 curpeers->conf.line = linenum;
1796 curpeers->last_change = now.tv_sec;
1797 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001798 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001799 }
1800 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001801 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001802 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001803 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001804
1805 if (!*args[2]) {
1806 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1807 file, linenum, args[0]);
1808 err_code |= ERR_ALERT | ERR_FATAL;
1809 goto out;
1810 }
1811
1812 err = invalid_char(args[1]);
1813 if (err) {
1814 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1815 file, linenum, *err, args[1]);
1816 err_code |= ERR_ALERT | ERR_FATAL;
1817 goto out;
1818 }
1819
1820 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1821 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1822 err_code |= ERR_ALERT | ERR_ABORT;
1823 goto out;
1824 }
1825
1826 /* the peers are linked backwards first */
1827 curpeers->count++;
1828 newpeer->next = curpeers->remote;
1829 curpeers->remote = newpeer;
1830 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001831 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001832 newpeer->conf.line = linenum;
1833
1834 newpeer->last_change = now.tv_sec;
1835 newpeer->id = strdup(args[1]);
1836
Willy Tarreau902636f2013-03-10 19:44:48 +01001837 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001838 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001839 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001840 err_code |= ERR_ALERT | ERR_FATAL;
1841 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001842 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001843
1844 proto = protocol_by_family(sk->ss_family);
1845 if (!proto || !proto->connect) {
1846 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1847 file, linenum, args[0], args[1]);
1848 err_code |= ERR_ALERT | ERR_FATAL;
1849 goto out;
1850 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001851
1852 if (port1 != port2) {
1853 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1854 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001855 err_code |= ERR_ALERT | ERR_FATAL;
1856 goto out;
1857 }
1858
Willy Tarreau2aa38802013-02-20 19:20:59 +01001859 if (!port1) {
1860 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1861 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001862 err_code |= ERR_ALERT | ERR_FATAL;
1863 goto out;
1864 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001865
Emeric Brun32da3c42010-09-23 18:39:19 +02001866 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001867 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001868 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001869 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001870
Emeric Brun32da3c42010-09-23 18:39:19 +02001871 if (strcmp(newpeer->id, localpeer) == 0) {
1872 /* Current is local peer, it define a frontend */
1873 newpeer->local = 1;
1874
1875 if (!curpeers->peers_fe) {
1876 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1877 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1878 err_code |= ERR_ALERT | ERR_ABORT;
1879 goto out;
1880 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001881
Willy Tarreau237250c2011-07-29 01:49:03 +02001882 init_new_proxy(curpeers->peers_fe);
1883 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001884 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001885 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1886 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01001887 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02001888
1889 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1890
Willy Tarreau902636f2013-03-10 19:44:48 +01001891 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1892 if (errmsg && *errmsg) {
1893 indent_msg(&errmsg, 2);
1894 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001895 }
1896 else
1897 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1898 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001899 err_code |= ERR_FATAL;
1900 goto out;
1901 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001902
1903 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001904 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001905 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1906 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02001907 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02001908 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001909 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01001910 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001911 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1912 global.maxsock += l->maxconn;
1913 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001914 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001915 else {
1916 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1917 file, linenum, args[0], args[1],
1918 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1919 err_code |= ERR_FATAL;
1920 goto out;
1921 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001922 }
1923 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001924 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
1925 curpeers->state = PR_STSTOPPED;
1926 }
1927 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
1928 curpeers->state = PR_STNEW;
1929 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001930 else if (*args[0] != 0) {
1931 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1932 err_code |= ERR_ALERT | ERR_FATAL;
1933 goto out;
1934 }
1935
1936out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001937 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001938 return err_code;
1939}
1940
Simon Horman0d16a402015-01-30 11:22:58 +09001941
1942/*
1943 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
1944 * Returns the error code, 0 if OK, or any combination of :
1945 * - ERR_ABORT: must abort ASAP
1946 * - ERR_FATAL: we can continue parsing but not start the service
1947 * - ERR_WARN: a warning has been emitted
1948 * - ERR_ALERT: an alert has been emitted
1949 * Only the two first ones can stop processing, the two others are just
1950 * indicators.
1951 */
1952int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
1953{
1954 static struct mailers *curmailers = NULL;
1955 struct mailer *newmailer = NULL;
1956 const char *err;
1957 int err_code = 0;
1958 char *errmsg = NULL;
1959
1960 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
1961 if (!*args[1]) {
1962 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
1963 err_code |= ERR_ALERT | ERR_ABORT;
1964 goto out;
1965 }
1966
1967 err = invalid_char(args[1]);
1968 if (err) {
1969 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1970 file, linenum, *err, args[0], args[1]);
1971 err_code |= ERR_ALERT | ERR_ABORT;
1972 goto out;
1973 }
1974
1975 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
1976 /*
1977 * If there are two proxies with the same name only following
1978 * combinations are allowed:
1979 */
1980 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001981 Alert("Parsing [%s:%d]: mailers section '%s' has the same name as another mailers section declared at %s:%d.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09001982 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001983 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09001984 }
1985 }
1986
1987 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
1988 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1989 err_code |= ERR_ALERT | ERR_ABORT;
1990 goto out;
1991 }
1992
1993 curmailers->next = mailers;
1994 mailers = curmailers;
1995 curmailers->conf.file = strdup(file);
1996 curmailers->conf.line = linenum;
1997 curmailers->id = strdup(args[1]);
1998 }
1999 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2000 struct sockaddr_storage *sk;
2001 int port1, port2;
2002 struct protocol *proto;
2003
2004 if (!*args[2]) {
2005 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2006 file, linenum, args[0]);
2007 err_code |= ERR_ALERT | ERR_FATAL;
2008 goto out;
2009 }
2010
2011 err = invalid_char(args[1]);
2012 if (err) {
2013 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2014 file, linenum, *err, args[1]);
2015 err_code |= ERR_ALERT | ERR_FATAL;
2016 goto out;
2017 }
2018
2019 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2020 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2021 err_code |= ERR_ALERT | ERR_ABORT;
2022 goto out;
2023 }
2024
2025 /* the mailers are linked backwards first */
2026 curmailers->count++;
2027 newmailer->next = curmailers->mailer_list;
2028 curmailers->mailer_list = newmailer;
2029 newmailer->mailers = curmailers;
2030 newmailer->conf.file = strdup(file);
2031 newmailer->conf.line = linenum;
2032
2033 newmailer->id = strdup(args[1]);
2034
2035 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2036 if (!sk) {
2037 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2038 err_code |= ERR_ALERT | ERR_FATAL;
2039 goto out;
2040 }
2041
2042 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002043 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2044 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002045 file, linenum, args[0], args[1]);
2046 err_code |= ERR_ALERT | ERR_FATAL;
2047 goto out;
2048 }
2049
2050 if (port1 != port2) {
2051 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2052 file, linenum, args[0], args[1], args[2]);
2053 err_code |= ERR_ALERT | ERR_FATAL;
2054 goto out;
2055 }
2056
2057 if (!port1) {
2058 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2059 file, linenum, args[0], args[1], args[2]);
2060 err_code |= ERR_ALERT | ERR_FATAL;
2061 goto out;
2062 }
2063
2064 newmailer->addr = *sk;
2065 newmailer->proto = proto;
2066 newmailer->xprt = &raw_sock;
2067 newmailer->sock_init_arg = NULL;
2068 } /* neither "mailer" nor "mailers" */
2069 else if (*args[0] != 0) {
2070 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2071 err_code |= ERR_ALERT | ERR_FATAL;
2072 goto out;
2073 }
2074
2075out:
2076 free(errmsg);
2077 return err_code;
2078}
2079
Simon Horman9dc49962015-01-30 11:22:59 +09002080static void free_email_alert(struct proxy *p)
2081{
2082 free(p->email_alert.mailers.name);
2083 p->email_alert.mailers.name = NULL;
2084 free(p->email_alert.from);
2085 p->email_alert.from = NULL;
2086 free(p->email_alert.to);
2087 p->email_alert.to = NULL;
2088 free(p->email_alert.myhostname);
2089 p->email_alert.myhostname = NULL;
2090}
2091
Willy Tarreau3842f002009-06-14 11:39:52 +02002092int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002093{
2094 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002095 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002096 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002097 int rc;
2098 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002099 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002100 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002101 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002102 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002103 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104
Willy Tarreau977b8e42006-12-29 14:19:17 +01002105 if (!strcmp(args[0], "listen"))
2106 rc = PR_CAP_LISTEN;
2107 else if (!strcmp(args[0], "frontend"))
2108 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002109 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002110 rc = PR_CAP_BE | PR_CAP_RS;
2111 else if (!strcmp(args[0], "ruleset"))
2112 rc = PR_CAP_RS;
2113 else
2114 rc = PR_CAP_NONE;
2115
2116 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002117 if (!*args[1]) {
2118 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2119 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2120 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002121 err_code |= ERR_ALERT | ERR_ABORT;
2122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002123 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002124
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002125 err = invalid_char(args[1]);
2126 if (err) {
2127 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2128 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002129 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002130 }
2131
Willy Tarreau8f50b682015-05-26 11:45:02 +02002132 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2133 if (curproxy) {
2134 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2135 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2136 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002137 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002138 }
2139
Willy Tarreaubaaee002006-06-26 02:48:02 +02002140 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2141 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002142 err_code |= ERR_ALERT | ERR_ABORT;
2143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002144 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002145
Willy Tarreau97cb7802010-01-03 20:23:58 +01002146 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002147 curproxy->next = proxy;
2148 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002149 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2150 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002151 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002152 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002153 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002154 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002155
2156 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002157 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002158 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02002159
Willy Tarreau4348fad2012-09-20 16:48:07 +02002160 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2161
Willy Tarreau902636f2013-03-10 19:44:48 +01002162 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2163 if (errmsg && *errmsg) {
2164 indent_msg(&errmsg, 2);
2165 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002166 }
2167 else
2168 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2169 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002170 err_code |= ERR_FATAL;
2171 goto out;
2172 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002173
Willy Tarreau4348fad2012-09-20 16:48:07 +02002174 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002175 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002176 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002177 }
2178
2179 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002180 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002181 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002182
Willy Tarreaubaaee002006-06-26 02:48:02 +02002183 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002184 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002185 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002186 curproxy->no_options = defproxy.no_options;
2187 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002188 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002189 curproxy->except_net = defproxy.except_net;
2190 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002191 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002192 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002193
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002194 if (defproxy.fwdfor_hdr_len) {
2195 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2196 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2197 }
2198
Willy Tarreaub86db342009-11-30 11:50:16 +01002199 if (defproxy.orgto_hdr_len) {
2200 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2201 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2202 }
2203
Mark Lamourinec2247f02012-01-04 13:02:01 -05002204 if (defproxy.server_id_hdr_len) {
2205 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2206 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2207 }
2208
Willy Tarreau977b8e42006-12-29 14:19:17 +01002209 if (curproxy->cap & PR_CAP_FE) {
2210 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002211 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002212 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002213
2214 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002215 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2216 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002217
2218 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2219 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002220
Willy Tarreau977b8e42006-12-29 14:19:17 +01002221 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002222 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002223 curproxy->fullconn = defproxy.fullconn;
2224 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002225 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002226 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002227
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002228 if (defproxy.check_req) {
2229 curproxy->check_req = calloc(1, defproxy.check_len);
2230 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2231 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002232 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002234 if (defproxy.expect_str) {
2235 curproxy->expect_str = strdup(defproxy.expect_str);
2236 if (defproxy.expect_regex) {
2237 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002238 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2239 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002240 }
2241 }
2242
Willy Tarreau67402132012-05-31 20:40:20 +02002243 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002244 if (defproxy.cookie_name)
2245 curproxy->cookie_name = strdup(defproxy.cookie_name);
2246 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002247 if (defproxy.cookie_domain)
2248 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002249
Willy Tarreau31936852010-10-06 16:59:56 +02002250 if (defproxy.cookie_maxidle)
2251 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2252
2253 if (defproxy.cookie_maxlife)
2254 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2255
Emeric Brun647caf12009-06-30 17:57:00 +02002256 if (defproxy.rdp_cookie_name)
2257 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2258 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2259
Willy Tarreau01732802007-11-01 22:48:15 +01002260 if (defproxy.url_param_name)
2261 curproxy->url_param_name = strdup(defproxy.url_param_name);
2262 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002263
Benoitaffb4812009-03-25 13:02:10 +01002264 if (defproxy.hh_name)
2265 curproxy->hh_name = strdup(defproxy.hh_name);
2266 curproxy->hh_len = defproxy.hh_len;
2267 curproxy->hh_match_domain = defproxy.hh_match_domain;
2268
Willy Tarreauef9a3602012-12-08 22:29:20 +01002269 if (defproxy.conn_src.iface_name)
2270 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2271 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002272 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002273#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002274 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002275#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002278 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002279 if (defproxy.capture_name)
2280 curproxy->capture_name = strdup(defproxy.capture_name);
2281 curproxy->capture_namelen = defproxy.capture_namelen;
2282 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002284
Willy Tarreau977b8e42006-12-29 14:19:17 +01002285 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002286 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002287 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002288 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002289 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002290 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002291 curproxy->mon_net = defproxy.mon_net;
2292 curproxy->mon_mask = defproxy.mon_mask;
2293 if (defproxy.monitor_uri)
2294 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2295 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002296 if (defproxy.defbe.name)
2297 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002298
2299 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002300 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2301 if (curproxy->conf.logformat_string &&
2302 curproxy->conf.logformat_string != default_http_log_format &&
2303 curproxy->conf.logformat_string != default_tcp_log_format &&
2304 curproxy->conf.logformat_string != clf_http_log_format)
2305 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2306
2307 if (defproxy.conf.lfs_file) {
2308 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2309 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2310 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002311 }
2312
2313 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002314 curproxy->timeout.connect = defproxy.timeout.connect;
2315 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002316 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002317 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002318 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002319 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002320 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002321 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002322 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002323 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002324 }
2325
Willy Tarreaubaaee002006-06-26 02:48:02 +02002326 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002327 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002328
2329 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002330 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002331 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002332 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002333 LIST_INIT(&node->list);
2334 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2335 }
2336
Willy Tarreau62a61232013-04-12 18:13:46 +02002337 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2338 if (curproxy->conf.uniqueid_format_string)
2339 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2340
Willy Tarreau094af4e2015-01-07 15:03:42 +01002341 if (defproxy.log_tag)
2342 curproxy->log_tag = strdup(defproxy.log_tag);
2343
Willy Tarreau62a61232013-04-12 18:13:46 +02002344 if (defproxy.conf.uif_file) {
2345 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2346 curproxy->conf.uif_line = defproxy.conf.uif_line;
2347 }
William Lallemanda73203e2012-03-12 12:48:57 +01002348
2349 /* copy default header unique id */
2350 if (defproxy.header_unique_id)
2351 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2352
William Lallemand82fe75c2012-10-23 10:25:10 +02002353 /* default compression options */
2354 if (defproxy.comp != NULL) {
2355 curproxy->comp = calloc(1, sizeof(struct comp));
2356 curproxy->comp->algos = defproxy.comp->algos;
2357 curproxy->comp->types = defproxy.comp->types;
2358 }
2359
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002361 curproxy->conf.used_listener_id = EB_ROOT;
2362 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002363
Simon Horman98637e52014-06-20 12:30:16 +09002364 if (defproxy.check_path)
2365 curproxy->check_path = strdup(defproxy.check_path);
2366 if (defproxy.check_command)
2367 curproxy->check_command = strdup(defproxy.check_command);
2368
Simon Horman9dc49962015-01-30 11:22:59 +09002369 if (defproxy.email_alert.mailers.name)
2370 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2371 if (defproxy.email_alert.from)
2372 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2373 if (defproxy.email_alert.to)
2374 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2375 if (defproxy.email_alert.myhostname)
2376 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002377 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002378
Willy Tarreau93893792009-07-23 13:19:11 +02002379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002380 }
2381 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2382 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002383 /* FIXME-20070101: we should do this too at the end of the
2384 * config parsing to free all default values.
2385 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002386 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002387 free(defproxy.check_command);
2388 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002389 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002390 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002391 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002392 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002393 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002394 free(defproxy.capture_name);
2395 free(defproxy.monitor_uri);
2396 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002397 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002398 free(defproxy.fwdfor_hdr_name);
2399 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002400 free(defproxy.orgto_hdr_name);
2401 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002402 free(defproxy.server_id_hdr_name);
2403 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002404 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002405 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002406 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002407 free(defproxy.expect_regex);
2408 defproxy.expect_regex = NULL;
2409 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002410
Willy Tarreau62a61232013-04-12 18:13:46 +02002411 if (defproxy.conf.logformat_string != default_http_log_format &&
2412 defproxy.conf.logformat_string != default_tcp_log_format &&
2413 defproxy.conf.logformat_string != clf_http_log_format)
2414 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002415
Willy Tarreau62a61232013-04-12 18:13:46 +02002416 free(defproxy.conf.uniqueid_format_string);
2417 free(defproxy.conf.lfs_file);
2418 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002419 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002420 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002421
Willy Tarreaua534fea2008-08-03 12:19:50 +02002422 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002423 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002424
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 /* we cannot free uri_auth because it might already be used */
2426 init_default_instance();
2427 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002428 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2429 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002430 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002432 }
2433 else if (curproxy == NULL) {
2434 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002437 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002438
2439 /* update the current file and line being parsed */
2440 curproxy->conf.args.file = curproxy->conf.file;
2441 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002442
2443 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002444 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2445 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2446 if (err_code & ERR_FATAL)
2447 goto out;
2448 }
2449 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002450 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002451 int cur_arg;
2452
Willy Tarreaubaaee002006-06-26 02:48:02 +02002453 if (curproxy == &defproxy) {
2454 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002455 err_code |= ERR_ALERT | ERR_FATAL;
2456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002457 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002458 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002459 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460
Willy Tarreau24709282013-03-10 21:32:12 +01002461 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002462 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002467
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002468 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002469
2470 /* use default settings for unix sockets */
2471 bind_conf->ux.uid = global.unix_bind.ux.uid;
2472 bind_conf->ux.gid = global.unix_bind.ux.gid;
2473 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002474
2475 /* NOTE: the following line might create several listeners if there
2476 * are comma-separated IPs or port ranges. So all further processing
2477 * will have to be applied to all listeners created after last_listen.
2478 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002479 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2480 if (errmsg && *errmsg) {
2481 indent_msg(&errmsg, 2);
2482 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002483 }
2484 else
2485 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2486 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
2489 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002490
Willy Tarreau4348fad2012-09-20 16:48:07 +02002491 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2492 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002493 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002494 }
2495
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002496 cur_arg = 2;
2497 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002498 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002499 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002500 char *err;
2501
Willy Tarreau26982662012-09-12 23:17:10 +02002502 kw = bind_find_kw(args[cur_arg]);
2503 if (kw) {
2504 char *err = NULL;
2505 int code;
2506
2507 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002508 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2509 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002510 cur_arg += 1 + kw->skip ;
2511 err_code |= ERR_ALERT | ERR_FATAL;
2512 goto out;
2513 }
2514
Willy Tarreau4348fad2012-09-20 16:48:07 +02002515 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002516 err_code |= code;
2517
2518 if (code) {
2519 if (err && *err) {
2520 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002521 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002522 }
2523 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002524 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2525 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002526 if (code & ERR_FATAL) {
2527 free(err);
2528 cur_arg += 1 + kw->skip;
2529 goto out;
2530 }
2531 }
2532 free(err);
2533 cur_arg += 1 + kw->skip;
2534 continue;
2535 }
2536
Willy Tarreau8638f482012-09-18 18:01:17 +02002537 err = NULL;
2538 if (!bind_dumped) {
2539 bind_dump_kws(&err);
2540 indent_msg(&err, 4);
2541 bind_dumped = 1;
2542 }
2543
2544 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2545 file, linenum, args[0], args[1], args[cur_arg],
2546 err ? " Registered keywords :" : "", err ? err : "");
2547 free(err);
2548
Willy Tarreau93893792009-07-23 13:19:11 +02002549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002551 }
Willy Tarreau93893792009-07-23 13:19:11 +02002552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 }
2554 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002555 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2557 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002558 err_code |= ERR_ALERT | ERR_FATAL;
2559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002561 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002562 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002563
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 /* flush useless bits */
2565 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002568 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002569 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002570 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002571
Willy Tarreau1c47f852006-07-09 08:22:27 +02002572 if (!*args[1]) {
2573 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2574 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002575 err_code |= ERR_ALERT | ERR_FATAL;
2576 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002577 }
2578
Willy Tarreaua534fea2008-08-03 12:19:50 +02002579 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002580 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002581 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002582 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002583 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2584
Willy Tarreau93893792009-07-23 13:19:11 +02002585 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2588 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2589 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2590 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2591 else {
2592 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002593 err_code |= ERR_ALERT | ERR_FATAL;
2594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 }
2596 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002597 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002598 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002599
2600 if (curproxy == &defproxy) {
2601 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2602 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002605 }
2606
2607 if (!*args[1]) {
2608 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2609 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002610 err_code |= ERR_ALERT | ERR_FATAL;
2611 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002612 }
2613
2614 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002615 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002616
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002617 if (curproxy->uuid <= 0) {
2618 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002619 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002620 err_code |= ERR_ALERT | ERR_FATAL;
2621 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002622 }
2623
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002624 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2625 if (node) {
2626 struct proxy *target = container_of(node, struct proxy, conf.id);
2627 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2628 file, linenum, proxy_type_str(curproxy), curproxy->id,
2629 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
2632 }
2633 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002634 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002635 else if (!strcmp(args[0], "description")) {
2636 int i, len=0;
2637 char *d;
2638
Cyril Bonté99ed3272010-01-24 23:29:44 +01002639 if (curproxy == &defproxy) {
2640 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2641 file, linenum, args[0]);
2642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
2644 }
2645
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002646 if (!*args[1]) {
2647 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2648 file, linenum, args[0]);
2649 return -1;
2650 }
2651
Willy Tarreau348acfe2014-04-14 15:00:39 +02002652 for (i = 1; *args[i]; i++)
2653 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002654
2655 d = (char *)calloc(1, len);
2656 curproxy->desc = d;
2657
Willy Tarreau348acfe2014-04-14 15:00:39 +02002658 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2659 for (i = 2; *args[i]; i++)
2660 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002661
2662 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002663 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2664 curproxy->state = PR_STSTOPPED;
2665 }
2666 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2667 curproxy->state = PR_STNEW;
2668 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002669 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2670 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002671 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002672
2673 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002674 unsigned int low, high;
2675
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002676 if (strcmp(args[cur_arg], "all") == 0) {
2677 set = 0;
2678 break;
2679 }
2680 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002681 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002682 }
2683 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002684 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002685 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002686 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002687 char *dash = strchr(args[cur_arg], '-');
2688
2689 low = high = str2uic(args[cur_arg]);
2690 if (dash)
2691 high = str2uic(dash + 1);
2692
2693 if (high < low) {
2694 unsigned int swap = low;
2695 low = high;
2696 high = swap;
2697 }
2698
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002699 if (low < 1 || high > LONGBITS) {
2700 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2701 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002702 err_code |= ERR_ALERT | ERR_FATAL;
2703 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002704 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002705 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002706 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002707 }
2708 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002709 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2710 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002711 err_code |= ERR_ALERT | ERR_FATAL;
2712 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002713 }
2714 cur_arg++;
2715 }
2716 curproxy->bind_proc = set;
2717 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002718 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002719 if (curproxy == &defproxy) {
2720 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002721 err_code |= ERR_ALERT | ERR_FATAL;
2722 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002723 }
2724
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002725 err = invalid_char(args[1]);
2726 if (err) {
2727 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2728 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002729 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002730 }
2731
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002732 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002733 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2734 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002735 err_code |= ERR_ALERT | ERR_FATAL;
2736 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002737 }
2738 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002739 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2740 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002741
Willy Tarreau977b8e42006-12-29 14:19:17 +01002742 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002743 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002744
Willy Tarreaubaaee002006-06-26 02:48:02 +02002745 if (*(args[1]) == 0) {
2746 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2747 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002748 err_code |= ERR_ALERT | ERR_FATAL;
2749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002750 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002751
Willy Tarreau67402132012-05-31 20:40:20 +02002752 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002753 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002754 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002755 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 curproxy->cookie_name = strdup(args[1]);
2757 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002758
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 cur_arg = 2;
2760 while (*(args[cur_arg])) {
2761 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002762 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 }
2764 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002765 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002766 }
2767 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002768 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002769 }
2770 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002771 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002772 }
2773 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002774 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002775 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002776 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002777 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002778 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002779 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002780 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002781 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002782 else if (!strcmp(args[cur_arg], "httponly")) {
2783 curproxy->ck_opts |= PR_CK_HTTPONLY;
2784 }
2785 else if (!strcmp(args[cur_arg], "secure")) {
2786 curproxy->ck_opts |= PR_CK_SECURE;
2787 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002788 else if (!strcmp(args[cur_arg], "domain")) {
2789 if (!*args[cur_arg + 1]) {
2790 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2791 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002794 }
2795
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002796 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002797 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002798 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2799 " dots nor does not start with a dot."
2800 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002801 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002802 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002803 }
2804
2805 err = invalid_domainchar(args[cur_arg + 1]);
2806 if (err) {
2807 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2808 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002809 err_code |= ERR_ALERT | ERR_FATAL;
2810 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002811 }
2812
Willy Tarreau68a897b2009-12-03 23:28:34 +01002813 if (!curproxy->cookie_domain) {
2814 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2815 } else {
2816 /* one domain was already specified, add another one by
2817 * building the string which will be returned along with
2818 * the cookie.
2819 */
2820 char *new_ptr;
2821 int new_len = strlen(curproxy->cookie_domain) +
2822 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2823 new_ptr = malloc(new_len);
2824 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2825 free(curproxy->cookie_domain);
2826 curproxy->cookie_domain = new_ptr;
2827 }
Willy Tarreau31936852010-10-06 16:59:56 +02002828 cur_arg++;
2829 }
2830 else if (!strcmp(args[cur_arg], "maxidle")) {
2831 unsigned int maxidle;
2832 const char *res;
2833
2834 if (!*args[cur_arg + 1]) {
2835 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2836 file, linenum, args[cur_arg]);
2837 err_code |= ERR_ALERT | ERR_FATAL;
2838 goto out;
2839 }
2840
2841 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2842 if (res) {
2843 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2844 file, linenum, *res, args[cur_arg]);
2845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
2847 }
2848 curproxy->cookie_maxidle = maxidle;
2849 cur_arg++;
2850 }
2851 else if (!strcmp(args[cur_arg], "maxlife")) {
2852 unsigned int maxlife;
2853 const char *res;
2854
2855 if (!*args[cur_arg + 1]) {
2856 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2857 file, linenum, args[cur_arg]);
2858 err_code |= ERR_ALERT | ERR_FATAL;
2859 goto out;
2860 }
2861
2862 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2863 if (res) {
2864 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2865 file, linenum, *res, args[cur_arg]);
2866 err_code |= ERR_ALERT | ERR_FATAL;
2867 goto out;
2868 }
2869 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002870 cur_arg++;
2871 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002873 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 +02002874 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002875 err_code |= ERR_ALERT | ERR_FATAL;
2876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002877 }
2878 cur_arg++;
2879 }
Willy Tarreau67402132012-05-31 20:40:20 +02002880 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002881 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2882 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002883 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002884 }
2885
Willy Tarreau67402132012-05-31 20:40:20 +02002886 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002887 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2888 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002889 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002891
Willy Tarreau67402132012-05-31 20:40:20 +02002892 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002893 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2894 file, linenum);
2895 err_code |= ERR_ALERT | ERR_FATAL;
2896 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09002898 else if (!strcmp(args[0], "email-alert")) {
2899 if (*(args[1]) == 0) {
2900 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2901 file, linenum, args[0]);
2902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
2904 }
2905
2906 if (!strcmp(args[1], "from")) {
2907 if (*(args[1]) == 0) {
2908 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2909 file, linenum, args[1]);
2910 err_code |= ERR_ALERT | ERR_FATAL;
2911 goto out;
2912 }
2913 free(curproxy->email_alert.from);
2914 curproxy->email_alert.from = strdup(args[2]);
2915 }
2916 else if (!strcmp(args[1], "mailers")) {
2917 if (*(args[1]) == 0) {
2918 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2919 file, linenum, args[1]);
2920 err_code |= ERR_ALERT | ERR_FATAL;
2921 goto out;
2922 }
2923 free(curproxy->email_alert.mailers.name);
2924 curproxy->email_alert.mailers.name = strdup(args[2]);
2925 }
2926 else if (!strcmp(args[1], "myhostname")) {
2927 if (*(args[1]) == 0) {
2928 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2929 file, linenum, args[1]);
2930 err_code |= ERR_ALERT | ERR_FATAL;
2931 goto out;
2932 }
2933 free(curproxy->email_alert.myhostname);
2934 curproxy->email_alert.myhostname = strdup(args[2]);
2935 }
Simon Horman64e34162015-02-06 11:11:57 +09002936 else if (!strcmp(args[1], "level")) {
2937 curproxy->email_alert.level = get_log_level(args[2]);
2938 if (curproxy->email_alert.level < 0) {
2939 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
2940 file, linenum, args[1], args[2]);
2941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
2943 }
2944 }
Simon Horman9dc49962015-01-30 11:22:59 +09002945 else if (!strcmp(args[1], "to")) {
2946 if (*(args[1]) == 0) {
2947 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2948 file, linenum, args[1]);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952 free(curproxy->email_alert.to);
2953 curproxy->email_alert.to = strdup(args[2]);
2954 }
2955 else {
2956 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
2957 file, linenum, args[1]);
2958 err_code |= ERR_ALERT | ERR_FATAL;
2959 goto out;
2960 }
Simon Horman64e34162015-02-06 11:11:57 +09002961 /* Indicate that the email_alert is at least partially configured */
2962 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09002963 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09002964 else if (!strcmp(args[0], "external-check")) {
2965 if (*(args[1]) == 0) {
2966 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2967 file, linenum, args[0]);
2968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
2970 }
2971
2972 if (!strcmp(args[1], "command")) {
2973 if (*(args[1]) == 0) {
2974 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2975 file, linenum, args[1]);
2976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
2978 }
2979 free(curproxy->check_command);
2980 curproxy->check_command = strdup(args[2]);
2981 }
2982 else if (!strcmp(args[1], "path")) {
2983 if (*(args[1]) == 0) {
2984 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2985 file, linenum, args[1]);
2986 err_code |= ERR_ALERT | ERR_FATAL;
2987 goto out;
2988 }
2989 free(curproxy->check_path);
2990 curproxy->check_path = strdup(args[2]);
2991 }
2992 else {
2993 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
2994 file, linenum, args[1]);
2995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
2997 }
2998 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002999 else if (!strcmp(args[0], "persist")) { /* persist */
3000 if (*(args[1]) == 0) {
3001 Alert("parsing [%s:%d] : missing persist method.\n",
3002 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003005 }
3006
3007 if (!strncmp(args[1], "rdp-cookie", 10)) {
3008 curproxy->options2 |= PR_O2_RDPC_PRST;
3009
Emeric Brunb982a3d2010-01-04 15:45:53 +01003010 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003011 const char *beg, *end;
3012
3013 beg = args[1] + 11;
3014 end = strchr(beg, ')');
3015
3016 if (!end || end == beg) {
3017 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3018 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003021 }
3022
3023 free(curproxy->rdp_cookie_name);
3024 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3025 curproxy->rdp_cookie_len = end-beg;
3026 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003027 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003028 free(curproxy->rdp_cookie_name);
3029 curproxy->rdp_cookie_name = strdup("msts");
3030 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3031 }
3032 else { /* syntax */
3033 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3034 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003037 }
3038 }
3039 else {
3040 Alert("parsing [%s:%d] : unknown persist method.\n",
3041 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003042 err_code |= ERR_ALERT | ERR_FATAL;
3043 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003044 }
3045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003047 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003048
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003049 if (curproxy == &defproxy) {
3050 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3051 err_code |= ERR_ALERT | ERR_FATAL;
3052 goto out;
3053 }
3054
Willy Tarreau977b8e42006-12-29 14:19:17 +01003055 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003056 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003057
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003059 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003060 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 }
3064 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003065 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066 curproxy->appsession_name = strdup(args[1]);
3067 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3068 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003069 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3070 if (err) {
3071 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3072 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003073 err_code |= ERR_ALERT | ERR_FATAL;
3074 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003075 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003076 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003077
Willy Tarreau51041c72007-09-09 21:56:53 +02003078 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3079 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003080 err_code |= ERR_ALERT | ERR_ABORT;
3081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003083
3084 cur_arg = 6;
3085 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003086 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3087 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003088 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003089 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003090 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003091 } else if (!strcmp(args[cur_arg], "prefix")) {
3092 curproxy->options2 |= PR_O2_AS_PFX;
3093 } else if (!strcmp(args[cur_arg], "mode")) {
3094 if (!*args[cur_arg + 1]) {
3095 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3096 file, linenum, args[0], args[cur_arg]);
3097 err_code |= ERR_ALERT | ERR_FATAL;
3098 goto out;
3099 }
3100
3101 cur_arg++;
3102 if (!strcmp(args[cur_arg], "query-string")) {
3103 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3104 curproxy->options2 |= PR_O2_AS_M_QS;
3105 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3106 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3107 curproxy->options2 |= PR_O2_AS_M_PP;
3108 } else {
3109 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
3112 }
3113 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003114 cur_arg++;
3115 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 } /* Url App Session */
3117 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003118 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003119 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003120
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003122 if (curproxy == &defproxy) {
3123 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3124 err_code |= ERR_ALERT | ERR_FATAL;
3125 goto out;
3126 }
3127
Willy Tarreaubaaee002006-06-26 02:48:02 +02003128 if (*(args[4]) == 0) {
3129 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3130 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003133 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003134 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 curproxy->capture_name = strdup(args[2]);
3136 curproxy->capture_namelen = strlen(curproxy->capture_name);
3137 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138 curproxy->to_log |= LW_COOKIE;
3139 }
3140 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3141 struct cap_hdr *hdr;
3142
3143 if (curproxy == &defproxy) {
3144 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 +02003145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 }
3148
3149 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3150 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3151 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003152 err_code |= ERR_ALERT | ERR_FATAL;
3153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 }
3155
3156 hdr = calloc(sizeof(struct cap_hdr), 1);
3157 hdr->next = curproxy->req_cap;
3158 hdr->name = strdup(args[3]);
3159 hdr->namelen = strlen(args[3]);
3160 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003161 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 hdr->index = curproxy->nb_req_cap++;
3163 curproxy->req_cap = hdr;
3164 curproxy->to_log |= LW_REQHDR;
3165 }
3166 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3167 struct cap_hdr *hdr;
3168
3169 if (curproxy == &defproxy) {
3170 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 +02003171 err_code |= ERR_ALERT | ERR_FATAL;
3172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 }
3174
3175 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3176 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3177 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003178 err_code |= ERR_ALERT | ERR_FATAL;
3179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 }
3181 hdr = calloc(sizeof(struct cap_hdr), 1);
3182 hdr->next = curproxy->rsp_cap;
3183 hdr->name = strdup(args[3]);
3184 hdr->namelen = strlen(args[3]);
3185 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003186 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003187 hdr->index = curproxy->nb_rsp_cap++;
3188 curproxy->rsp_cap = hdr;
3189 curproxy->to_log |= LW_RSPHDR;
3190 }
3191 else {
3192 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3193 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003194 err_code |= ERR_ALERT | ERR_FATAL;
3195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 }
3197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003199 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003200 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003201
Willy Tarreaubaaee002006-06-26 02:48:02 +02003202 if (*(args[1]) == 0) {
3203 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3204 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 }
3208 curproxy->conn_retries = atol(args[1]);
3209 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003210 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003211 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003212
3213 if (curproxy == &defproxy) {
3214 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
3217 }
3218
Willy Tarreau20b0de52012-12-24 15:45:22 +01003219 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3220 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3221 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3222 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003223 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003224 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3225 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 +01003226 file, linenum, args[0]);
3227 err_code |= ERR_WARN;
3228 }
3229
Willy Tarreauff011f22011-01-06 17:51:27 +01003230 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003231
Willy Tarreauff011f22011-01-06 17:51:27 +01003232 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003233 err_code |= ERR_ALERT | ERR_ABORT;
3234 goto out;
3235 }
3236
Willy Tarreau5002f572014-04-23 01:32:02 +02003237 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003238 err_code |= warnif_cond_conflicts(rule->cond,
3239 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3240 file, linenum);
3241
Willy Tarreauff011f22011-01-06 17:51:27 +01003242 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003243 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003244 else if (!strcmp(args[0], "http-response")) { /* response access control */
3245 struct http_res_rule *rule;
3246
3247 if (curproxy == &defproxy) {
3248 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3249 err_code |= ERR_ALERT | ERR_FATAL;
3250 goto out;
3251 }
3252
3253 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3254 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3255 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3256 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3257 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3258 file, linenum, args[0]);
3259 err_code |= ERR_WARN;
3260 }
3261
3262 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3263
3264 if (!rule) {
3265 err_code |= ERR_ALERT | ERR_ABORT;
3266 goto out;
3267 }
3268
3269 err_code |= warnif_cond_conflicts(rule->cond,
3270 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3271 file, linenum);
3272
3273 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3274 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003275 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3276 /* set the header name and length into the proxy structure */
3277 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3278 err_code |= ERR_WARN;
3279
3280 if (!*args[1]) {
3281 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3282 file, linenum, args[0]);
3283 err_code |= ERR_ALERT | ERR_FATAL;
3284 goto out;
3285 }
3286
3287 /* set the desired header name */
3288 free(curproxy->server_id_hdr_name);
3289 curproxy->server_id_hdr_name = strdup(args[1]);
3290 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3291 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003292 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003293 struct http_req_rule *rule;
3294
Willy Tarreaub099aca2008-10-12 17:26:37 +02003295 if (curproxy == &defproxy) {
3296 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003297 err_code |= ERR_ALERT | ERR_FATAL;
3298 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003299 }
3300
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003301 /* emulate "block" using "http-request block". Since these rules are supposed to
3302 * be processed before all http-request rules, we put them into their own list
3303 * and will insert them at the end.
3304 */
3305 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3306 if (!rule) {
3307 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003308 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003309 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003310 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3311 err_code |= warnif_cond_conflicts(rule->cond,
3312 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3313 file, linenum);
3314 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003315
3316 if (!already_warned(WARN_BLOCK_DEPRECATED))
3317 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]);
3318
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003319 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003320 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003321 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003322
Cyril Bonté99ed3272010-01-24 23:29:44 +01003323 if (curproxy == &defproxy) {
3324 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
3327 }
3328
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003329 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003330 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3331 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003332 err_code |= ERR_ALERT | ERR_FATAL;
3333 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003334 }
3335
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003336 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003337 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003338 err_code |= warnif_cond_conflicts(rule->cond,
3339 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3340 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003341 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003342 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003343 struct switching_rule *rule;
3344
Willy Tarreaub099aca2008-10-12 17:26:37 +02003345 if (curproxy == &defproxy) {
3346 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003349 }
3350
Willy Tarreau55ea7572007-06-17 19:56:27 +02003351 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003352 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003353
3354 if (*(args[1]) == 0) {
3355 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003356 err_code |= ERR_ALERT | ERR_FATAL;
3357 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003358 }
3359
Willy Tarreauf51658d2014-04-23 01:21:56 +02003360 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3361 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3362 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3363 file, linenum, errmsg);
3364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
3366 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003367
Willy Tarreauf51658d2014-04-23 01:21:56 +02003368 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003369 }
3370
3371 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3372 rule->cond = cond;
3373 rule->be.name = strdup(args[1]);
3374 LIST_INIT(&rule->list);
3375 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3376 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003377 else if (strcmp(args[0], "use-server") == 0) {
3378 struct server_rule *rule;
3379
3380 if (curproxy == &defproxy) {
3381 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3382 err_code |= ERR_ALERT | ERR_FATAL;
3383 goto out;
3384 }
3385
3386 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3387 err_code |= ERR_WARN;
3388
3389 if (*(args[1]) == 0) {
3390 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
3393 }
3394
3395 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3396 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3397 file, linenum, args[0]);
3398 err_code |= ERR_ALERT | ERR_FATAL;
3399 goto out;
3400 }
3401
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003402 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3403 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3404 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
3407 }
3408
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003409 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003410
3411 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3412 rule->cond = cond;
3413 rule->srv.name = strdup(args[1]);
3414 LIST_INIT(&rule->list);
3415 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3416 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3417 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003418 else if ((!strcmp(args[0], "force-persist")) ||
3419 (!strcmp(args[0], "ignore-persist"))) {
3420 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003421
3422 if (curproxy == &defproxy) {
3423 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3424 err_code |= ERR_ALERT | ERR_FATAL;
3425 goto out;
3426 }
3427
3428 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3429 err_code |= ERR_WARN;
3430
Willy Tarreauef6494c2010-01-28 17:12:36 +01003431 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003432 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3433 file, linenum, args[0]);
3434 err_code |= ERR_ALERT | ERR_FATAL;
3435 goto out;
3436 }
3437
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003438 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3439 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3440 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003441 err_code |= ERR_ALERT | ERR_FATAL;
3442 goto out;
3443 }
3444
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003445 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3446 * where force-persist is applied.
3447 */
3448 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003449
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003450 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003451 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003452 if (!strcmp(args[0], "force-persist")) {
3453 rule->type = PERSIST_TYPE_FORCE;
3454 } else {
3455 rule->type = PERSIST_TYPE_IGNORE;
3456 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003457 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003458 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003459 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003460 else if (!strcmp(args[0], "stick-table")) {
3461 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003462 struct proxy *other;
3463
3464 other = find_stktable(curproxy->id);
3465 if (other) {
3466 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3467 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3468 err_code |= ERR_ALERT | ERR_FATAL;
3469 goto out;
3470 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003471
Emeric Brun32da3c42010-09-23 18:39:19 +02003472 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003473 curproxy->table.type = (unsigned int)-1;
3474 while (*args[myidx]) {
3475 const char *err;
3476
3477 if (strcmp(args[myidx], "size") == 0) {
3478 myidx++;
3479 if (!*(args[myidx])) {
3480 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3481 file, linenum, args[myidx-1]);
3482 err_code |= ERR_ALERT | ERR_FATAL;
3483 goto out;
3484 }
3485 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3486 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3487 file, linenum, *err, args[myidx-1]);
3488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
3490 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003491 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003492 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003493 else if (strcmp(args[myidx], "peers") == 0) {
3494 myidx++;
Godbach50523162013-12-11 19:48:57 +08003495 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003496 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3497 file, linenum, args[myidx-1]);
3498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
Godbach50523162013-12-11 19:48:57 +08003500 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003501 curproxy->table.peers.name = strdup(args[myidx++]);
3502 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003503 else if (strcmp(args[myidx], "expire") == 0) {
3504 myidx++;
3505 if (!*(args[myidx])) {
3506 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3507 file, linenum, args[myidx-1]);
3508 err_code |= ERR_ALERT | ERR_FATAL;
3509 goto out;
3510 }
3511 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3512 if (err) {
3513 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3514 file, linenum, *err, args[myidx-1]);
3515 err_code |= ERR_ALERT | ERR_FATAL;
3516 goto out;
3517 }
3518 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003519 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003520 }
3521 else if (strcmp(args[myidx], "nopurge") == 0) {
3522 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003523 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003524 }
3525 else if (strcmp(args[myidx], "type") == 0) {
3526 myidx++;
3527 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3528 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3529 file, linenum, args[myidx]);
3530 err_code |= ERR_ALERT | ERR_FATAL;
3531 goto out;
3532 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003533 /* myidx already points to next arg */
3534 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003535 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003536 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003537 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003538
3539 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003540 nw = args[myidx];
3541 while (*nw) {
3542 /* the "store" keyword supports a comma-separated list */
3543 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003544 sa = NULL; /* store arg */
3545 while (*nw && *nw != ',') {
3546 if (*nw == '(') {
3547 *nw = 0;
3548 sa = ++nw;
3549 while (*nw != ')') {
3550 if (!*nw) {
3551 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3552 file, linenum, args[0], cw);
3553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
3555 }
3556 nw++;
3557 }
3558 *nw = '\0';
3559 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003560 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003561 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003562 if (*nw)
3563 *nw++ = '\0';
3564 type = stktable_get_data_type(cw);
3565 if (type < 0) {
3566 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3567 file, linenum, args[0], cw);
3568 err_code |= ERR_ALERT | ERR_FATAL;
3569 goto out;
3570 }
Willy Tarreauac782882010-06-20 10:41:54 +02003571
3572 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3573 switch (err) {
3574 case PE_NONE: break;
3575 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003576 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3577 file, linenum, args[0], cw);
3578 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003579 break;
3580
3581 case PE_ARG_MISSING:
3582 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3583 file, linenum, args[0], cw);
3584 err_code |= ERR_ALERT | ERR_FATAL;
3585 goto out;
3586
3587 case PE_ARG_NOT_USED:
3588 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3589 file, linenum, args[0], cw);
3590 err_code |= ERR_ALERT | ERR_FATAL;
3591 goto out;
3592
3593 default:
3594 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3595 file, linenum, args[0], cw);
3596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003598 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003599 }
3600 myidx++;
3601 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003602 else {
3603 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3604 file, linenum, args[myidx]);
3605 err_code |= ERR_ALERT | ERR_FATAL;
3606 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003607 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003608 }
3609
3610 if (!curproxy->table.size) {
3611 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3612 file, linenum);
3613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
3615 }
3616
3617 if (curproxy->table.type == (unsigned int)-1) {
3618 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3619 file, linenum);
3620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
3622 }
3623 }
3624 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003625 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003626 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003627 int myidx = 0;
3628 const char *name = NULL;
3629 int flags;
3630
3631 if (curproxy == &defproxy) {
3632 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
3635 }
3636
3637 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3638 err_code |= ERR_WARN;
3639 goto out;
3640 }
3641
3642 myidx++;
3643 if ((strcmp(args[myidx], "store") == 0) ||
3644 (strcmp(args[myidx], "store-request") == 0)) {
3645 myidx++;
3646 flags = STK_IS_STORE;
3647 }
3648 else if (strcmp(args[myidx], "store-response") == 0) {
3649 myidx++;
3650 flags = STK_IS_STORE | STK_ON_RSP;
3651 }
3652 else if (strcmp(args[myidx], "match") == 0) {
3653 myidx++;
3654 flags = STK_IS_MATCH;
3655 }
3656 else if (strcmp(args[myidx], "on") == 0) {
3657 myidx++;
3658 flags = STK_IS_MATCH | STK_IS_STORE;
3659 }
3660 else {
3661 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3662 err_code |= ERR_ALERT | ERR_FATAL;
3663 goto out;
3664 }
3665
3666 if (*(args[myidx]) == 0) {
3667 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3668 err_code |= ERR_ALERT | ERR_FATAL;
3669 goto out;
3670 }
3671
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003672 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003673 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003674 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003675 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003676 err_code |= ERR_ALERT | ERR_FATAL;
3677 goto out;
3678 }
3679
3680 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003681 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3682 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3683 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003684 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003685 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003686 goto out;
3687 }
3688 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003689 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3690 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3691 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003692 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003693 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003694 goto out;
3695 }
3696 }
3697
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003698 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003699 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003700
Emeric Brunb982a3d2010-01-04 15:45:53 +01003701 if (strcmp(args[myidx], "table") == 0) {
3702 myidx++;
3703 name = args[myidx++];
3704 }
3705
Willy Tarreauef6494c2010-01-28 17:12:36 +01003706 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003707 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3708 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3709 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003710 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003711 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003712 goto out;
3713 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003714 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003715 else if (*(args[myidx])) {
3716 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3717 file, linenum, args[0], args[myidx]);
3718 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003719 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003720 goto out;
3721 }
Emeric Brun97679e72010-09-23 17:56:44 +02003722 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003723 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003724 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003725 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003726
Emeric Brunb982a3d2010-01-04 15:45:53 +01003727 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3728 rule->cond = cond;
3729 rule->expr = expr;
3730 rule->flags = flags;
3731 rule->table.name = name ? strdup(name) : NULL;
3732 LIST_INIT(&rule->list);
3733 if (flags & STK_ON_RSP)
3734 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3735 else
3736 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3737 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003738 else if (!strcmp(args[0], "stats")) {
3739 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3740 curproxy->uri_auth = NULL; /* we must detach from the default config */
3741
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003742 if (!*args[1]) {
3743 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003744 } else if (!strcmp(args[1], "admin")) {
3745 struct stats_admin_rule *rule;
3746
3747 if (curproxy == &defproxy) {
3748 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3749 err_code |= ERR_ALERT | ERR_FATAL;
3750 goto out;
3751 }
3752
3753 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3754 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3755 err_code |= ERR_ALERT | ERR_ABORT;
3756 goto out;
3757 }
3758
3759 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3760 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3761 file, linenum, args[0], args[1]);
3762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
3764 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003765 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3766 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3767 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003768 err_code |= ERR_ALERT | ERR_FATAL;
3769 goto out;
3770 }
3771
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003772 err_code |= warnif_cond_conflicts(cond,
3773 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3774 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003775
3776 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3777 rule->cond = cond;
3778 LIST_INIT(&rule->list);
3779 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003780 } else if (!strcmp(args[1], "uri")) {
3781 if (*(args[2]) == 0) {
3782 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003783 err_code |= ERR_ALERT | ERR_FATAL;
3784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003785 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3786 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_ABORT;
3788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003789 }
3790 } else if (!strcmp(args[1], "realm")) {
3791 if (*(args[2]) == 0) {
3792 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003795 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3796 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003797 err_code |= ERR_ALERT | ERR_ABORT;
3798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003799 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003800 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003801 unsigned interval;
3802
3803 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3804 if (err) {
3805 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3806 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003809 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3810 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003811 err_code |= ERR_ALERT | ERR_ABORT;
3812 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003813 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003814 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003815 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003816
3817 if (curproxy == &defproxy) {
3818 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3819 err_code |= ERR_ALERT | ERR_FATAL;
3820 goto out;
3821 }
3822
3823 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3824 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3825 err_code |= ERR_ALERT | ERR_ABORT;
3826 goto out;
3827 }
3828
Willy Tarreauff011f22011-01-06 17:51:27 +01003829 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3830 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003831 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3832 file, linenum, args[0]);
3833 err_code |= ERR_WARN;
3834 }
3835
Willy Tarreauff011f22011-01-06 17:51:27 +01003836 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003837
Willy Tarreauff011f22011-01-06 17:51:27 +01003838 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003839 err_code |= ERR_ALERT | ERR_ABORT;
3840 goto out;
3841 }
3842
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003843 err_code |= warnif_cond_conflicts(rule->cond,
3844 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3845 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003846 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003847
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 } else if (!strcmp(args[1], "auth")) {
3849 if (*(args[2]) == 0) {
3850 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003851 err_code |= ERR_ALERT | ERR_FATAL;
3852 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003853 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3854 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003855 err_code |= ERR_ALERT | ERR_ABORT;
3856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003857 }
3858 } else if (!strcmp(args[1], "scope")) {
3859 if (*(args[2]) == 0) {
3860 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003861 err_code |= ERR_ALERT | ERR_FATAL;
3862 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003863 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3864 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003865 err_code |= ERR_ALERT | ERR_ABORT;
3866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003867 }
3868 } else if (!strcmp(args[1], "enable")) {
3869 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3870 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_ALERT | ERR_ABORT;
3872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003874 } else if (!strcmp(args[1], "hide-version")) {
3875 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3876 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003877 err_code |= ERR_ALERT | ERR_ABORT;
3878 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003879 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003880 } else if (!strcmp(args[1], "show-legends")) {
3881 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3882 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3883 err_code |= ERR_ALERT | ERR_ABORT;
3884 goto out;
3885 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003886 } else if (!strcmp(args[1], "show-node")) {
3887
3888 if (*args[2]) {
3889 int i;
3890 char c;
3891
3892 for (i=0; args[2][i]; i++) {
3893 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003894 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3895 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003896 break;
3897 }
3898
3899 if (!i || args[2][i]) {
3900 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3901 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3902 file, linenum, args[0], args[1]);
3903 err_code |= ERR_ALERT | ERR_FATAL;
3904 goto out;
3905 }
3906 }
3907
3908 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3909 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3910 err_code |= ERR_ALERT | ERR_ABORT;
3911 goto out;
3912 }
3913 } else if (!strcmp(args[1], "show-desc")) {
3914 char *desc = NULL;
3915
3916 if (*args[2]) {
3917 int i, len=0;
3918 char *d;
3919
Willy Tarreau348acfe2014-04-14 15:00:39 +02003920 for (i = 2; *args[i]; i++)
3921 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003922
3923 desc = d = (char *)calloc(1, len);
3924
Willy Tarreau348acfe2014-04-14 15:00:39 +02003925 d += snprintf(d, desc + len - d, "%s", args[2]);
3926 for (i = 3; *args[i]; i++)
3927 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003928 }
3929
3930 if (!*args[2] && !global.desc)
3931 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3932 file, linenum, args[1]);
3933 else {
3934 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3935 free(desc);
3936 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3937 err_code |= ERR_ALERT | ERR_ABORT;
3938 goto out;
3939 }
3940 free(desc);
3941 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003942 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003943stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003944 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 +01003945 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003948 }
3949 }
3950 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003951 int optnum;
3952
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003953 if (*(args[1]) == '\0') {
3954 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3955 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003956 err_code |= ERR_ALERT | ERR_FATAL;
3957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003958 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003959
3960 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3961 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003962 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3963 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3964 file, linenum, cfg_opts[optnum].name);
3965 err_code |= ERR_ALERT | ERR_FATAL;
3966 goto out;
3967 }
Willy Tarreau93893792009-07-23 13:19:11 +02003968 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3969 err_code |= ERR_WARN;
3970 goto out;
3971 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003972
Willy Tarreau3842f002009-06-14 11:39:52 +02003973 curproxy->no_options &= ~cfg_opts[optnum].val;
3974 curproxy->options &= ~cfg_opts[optnum].val;
3975
3976 switch (kwm) {
3977 case KWM_STD:
3978 curproxy->options |= cfg_opts[optnum].val;
3979 break;
3980 case KWM_NO:
3981 curproxy->no_options |= cfg_opts[optnum].val;
3982 break;
3983 case KWM_DEF: /* already cleared */
3984 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003985 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003986
Willy Tarreau93893792009-07-23 13:19:11 +02003987 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003988 }
3989 }
3990
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003991 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3992 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003993 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3994 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3995 file, linenum, cfg_opts2[optnum].name);
3996 err_code |= ERR_ALERT | ERR_FATAL;
3997 goto out;
3998 }
Willy Tarreau93893792009-07-23 13:19:11 +02003999 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4000 err_code |= ERR_WARN;
4001 goto out;
4002 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004003
Willy Tarreau3842f002009-06-14 11:39:52 +02004004 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4005 curproxy->options2 &= ~cfg_opts2[optnum].val;
4006
4007 switch (kwm) {
4008 case KWM_STD:
4009 curproxy->options2 |= cfg_opts2[optnum].val;
4010 break;
4011 case KWM_NO:
4012 curproxy->no_options2 |= cfg_opts2[optnum].val;
4013 break;
4014 case KWM_DEF: /* already cleared */
4015 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004016 }
Willy Tarreau93893792009-07-23 13:19:11 +02004017 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004018 }
4019 }
4020
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004021 /* HTTP options override each other. They can be cancelled using
4022 * "no option xxx" which only switches to default mode if the mode
4023 * was this one (useful for cancelling options set in defaults
4024 * sections).
4025 */
4026 if (strcmp(args[1], "httpclose") == 0) {
4027 if (kwm == KWM_STD) {
4028 curproxy->options &= ~PR_O_HTTP_MODE;
4029 curproxy->options |= PR_O_HTTP_PCL;
4030 goto out;
4031 }
4032 else if (kwm == KWM_NO) {
4033 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4034 curproxy->options &= ~PR_O_HTTP_MODE;
4035 goto out;
4036 }
4037 }
4038 else if (strcmp(args[1], "forceclose") == 0) {
4039 if (kwm == KWM_STD) {
4040 curproxy->options &= ~PR_O_HTTP_MODE;
4041 curproxy->options |= PR_O_HTTP_FCL;
4042 goto out;
4043 }
4044 else if (kwm == KWM_NO) {
4045 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4046 curproxy->options &= ~PR_O_HTTP_MODE;
4047 goto out;
4048 }
4049 }
4050 else if (strcmp(args[1], "http-server-close") == 0) {
4051 if (kwm == KWM_STD) {
4052 curproxy->options &= ~PR_O_HTTP_MODE;
4053 curproxy->options |= PR_O_HTTP_SCL;
4054 goto out;
4055 }
4056 else if (kwm == KWM_NO) {
4057 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4058 curproxy->options &= ~PR_O_HTTP_MODE;
4059 goto out;
4060 }
4061 }
4062 else if (strcmp(args[1], "http-keep-alive") == 0) {
4063 if (kwm == KWM_STD) {
4064 curproxy->options &= ~PR_O_HTTP_MODE;
4065 curproxy->options |= PR_O_HTTP_KAL;
4066 goto out;
4067 }
4068 else if (kwm == KWM_NO) {
4069 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4070 curproxy->options &= ~PR_O_HTTP_MODE;
4071 goto out;
4072 }
4073 }
4074 else if (strcmp(args[1], "http-tunnel") == 0) {
4075 if (kwm == KWM_STD) {
4076 curproxy->options &= ~PR_O_HTTP_MODE;
4077 curproxy->options |= PR_O_HTTP_TUN;
4078 goto out;
4079 }
4080 else if (kwm == KWM_NO) {
4081 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4082 curproxy->options &= ~PR_O_HTTP_MODE;
4083 goto out;
4084 }
4085 }
4086
Joseph Lynch726ab712015-05-11 23:25:34 -07004087 /* Redispatch can take an integer argument that control when the
4088 * resispatch occurs. All values are relative to the retries option.
4089 * This can be cancelled using "no option xxx".
4090 */
4091 if (strcmp(args[1], "redispatch") == 0) {
4092 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4093 err_code |= ERR_WARN;
4094 goto out;
4095 }
4096
4097 curproxy->no_options &= ~PR_O_REDISP;
4098 curproxy->options &= ~PR_O_REDISP;
4099
4100 switch (kwm) {
4101 case KWM_STD:
4102 curproxy->options |= PR_O_REDISP;
4103 curproxy->redispatch_after = -1;
4104 if(*args[2]) {
4105 curproxy->redispatch_after = atol(args[2]);
4106 }
4107 break;
4108 case KWM_NO:
4109 curproxy->no_options |= PR_O_REDISP;
4110 curproxy->redispatch_after = 0;
4111 break;
4112 case KWM_DEF: /* already cleared */
4113 break;
4114 }
4115 goto out;
4116 }
4117
Willy Tarreau3842f002009-06-14 11:39:52 +02004118 if (kwm != KWM_STD) {
4119 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004120 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004121 err_code |= ERR_ALERT | ERR_FATAL;
4122 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004123 }
4124
Emeric Brun3a058f32009-06-30 18:26:00 +02004125 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004126 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004127 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004128 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004129 if (*(args[2]) != '\0') {
4130 if (!strcmp(args[2], "clf")) {
4131 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004132 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004133 } else {
4134 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02004135 err_code |= ERR_ALERT | ERR_FATAL;
4136 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004137 }
4138 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004139 if (curproxy->conf.logformat_string != default_http_log_format &&
4140 curproxy->conf.logformat_string != default_tcp_log_format &&
4141 curproxy->conf.logformat_string != clf_http_log_format)
4142 free(curproxy->conf.logformat_string);
4143 curproxy->conf.logformat_string = logformat;
4144
4145 free(curproxy->conf.lfs_file);
4146 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4147 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004148 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004149 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004150 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004151 if (curproxy->conf.logformat_string != default_http_log_format &&
4152 curproxy->conf.logformat_string != default_tcp_log_format &&
4153 curproxy->conf.logformat_string != clf_http_log_format)
4154 free(curproxy->conf.logformat_string);
4155 curproxy->conf.logformat_string = default_tcp_log_format;
4156
4157 free(curproxy->conf.lfs_file);
4158 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4159 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004160 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004161 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004162 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004163 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004164 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004165
4166 if (curproxy->cap & PR_CAP_FE)
4167 curproxy->options |= PR_O_TCP_CLI_KA;
4168 if (curproxy->cap & PR_CAP_BE)
4169 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004170 }
4171 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004172 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004173 err_code |= ERR_WARN;
4174
Willy Tarreaubaaee002006-06-26 02:48:02 +02004175 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004176 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004177 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004178 curproxy->options2 &= ~PR_O2_CHK_ANY;
4179 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004180 if (!*args[2]) { /* no argument */
4181 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4182 curproxy->check_len = strlen(DEF_CHECK_REQ);
4183 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004184 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004185 curproxy->check_req = (char *)malloc(reqlen);
4186 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004187 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004188 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004189 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004190 if (*args[4])
4191 reqlen += strlen(args[4]);
4192 else
4193 reqlen += strlen("HTTP/1.0");
4194
4195 curproxy->check_req = (char *)malloc(reqlen);
4196 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004197 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004198 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004199 }
4200 else if (!strcmp(args[1], "ssl-hello-chk")) {
4201 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004202 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004203 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004204
Willy Tarreaua534fea2008-08-03 12:19:50 +02004205 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004206 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004207 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004208 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004209 }
Willy Tarreau23677902007-05-08 23:50:35 +02004210 else if (!strcmp(args[1], "smtpchk")) {
4211 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004212 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004213 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004214 curproxy->options2 &= ~PR_O2_CHK_ANY;
4215 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004216
4217 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4218 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4219 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4220 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4221 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4222 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4223 curproxy->check_req = (char *)malloc(reqlen);
4224 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4225 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4226 } else {
4227 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4228 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4229 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4230 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4231 }
4232 }
4233 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004234 else if (!strcmp(args[1], "pgsql-check")) {
4235 /* use PostgreSQL request to check servers' health */
4236 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4237 err_code |= ERR_WARN;
4238
4239 free(curproxy->check_req);
4240 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004241 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004242 curproxy->options2 |= PR_O2_PGSQL_CHK;
4243
4244 if (*(args[2])) {
4245 int cur_arg = 2;
4246
4247 while (*(args[cur_arg])) {
4248 if (strcmp(args[cur_arg], "user") == 0) {
4249 char * packet;
4250 uint32_t packet_len;
4251 uint32_t pv;
4252
4253 /* suboption header - needs additional argument for it */
4254 if (*(args[cur_arg+1]) == 0) {
4255 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4256 file, linenum, args[0], args[1], args[cur_arg]);
4257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
4259 }
4260
4261 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4262 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4263 pv = htonl(0x30000); /* protocol version 3.0 */
4264
4265 packet = (char*) calloc(1, packet_len);
4266
4267 memcpy(packet + 4, &pv, 4);
4268
4269 /* copy "user" */
4270 memcpy(packet + 8, "user", 4);
4271
4272 /* copy username */
4273 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4274
4275 free(curproxy->check_req);
4276 curproxy->check_req = packet;
4277 curproxy->check_len = packet_len;
4278
4279 packet_len = htonl(packet_len);
4280 memcpy(packet, &packet_len, 4);
4281 cur_arg += 2;
4282 } else {
4283 /* unknown suboption - catchall */
4284 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4285 file, linenum, args[0], args[1]);
4286 err_code |= ERR_ALERT | ERR_FATAL;
4287 goto out;
4288 }
4289 } /* end while loop */
4290 }
4291 }
4292
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004293 else if (!strcmp(args[1], "redis-check")) {
4294 /* use REDIS PING request to check servers' health */
4295 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4296 err_code |= ERR_WARN;
4297
4298 free(curproxy->check_req);
4299 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004300 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004301 curproxy->options2 |= PR_O2_REDIS_CHK;
4302
4303 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4304 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4305 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4306 }
4307
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004308 else if (!strcmp(args[1], "mysql-check")) {
4309 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004310 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4311 err_code |= ERR_WARN;
4312
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004313 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004314 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004315 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004316 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004317
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004318 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004319 * const char mysql40_client_auth_pkt[] = {
4320 * "\x0e\x00\x00" // packet length
4321 * "\x01" // packet number
4322 * "\x00\x00" // client capabilities
4323 * "\x00\x00\x01" // max packet
4324 * "haproxy\x00" // username (null terminated string)
4325 * "\x00" // filler (always 0x00)
4326 * "\x01\x00\x00" // packet length
4327 * "\x00" // packet number
4328 * "\x01" // COM_QUIT command
4329 * };
4330 */
4331
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004332 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4333 * const char mysql41_client_auth_pkt[] = {
4334 * "\x0e\x00\x00\" // packet length
4335 * "\x01" // packet number
4336 * "\x00\x00\x00\x00" // client capabilities
4337 * "\x00\x00\x00\x01" // max packet
4338 * "\x21" // character set (UTF-8)
4339 * char[23] // All zeroes
4340 * "haproxy\x00" // username (null terminated string)
4341 * "\x00" // filler (always 0x00)
4342 * "\x01\x00\x00" // packet length
4343 * "\x00" // packet number
4344 * "\x01" // COM_QUIT command
4345 * };
4346 */
4347
4348
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004349 if (*(args[2])) {
4350 int cur_arg = 2;
4351
4352 while (*(args[cur_arg])) {
4353 if (strcmp(args[cur_arg], "user") == 0) {
4354 char *mysqluser;
4355 int packetlen, reqlen, userlen;
4356
4357 /* suboption header - needs additional argument for it */
4358 if (*(args[cur_arg+1]) == 0) {
4359 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4360 file, linenum, args[0], args[1], args[cur_arg]);
4361 err_code |= ERR_ALERT | ERR_FATAL;
4362 goto out;
4363 }
4364 mysqluser = args[cur_arg + 1];
4365 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004366
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004367 if (*(args[cur_arg+2])) {
4368 if (!strcmp(args[cur_arg+2], "post-41")) {
4369 packetlen = userlen + 7 + 27;
4370 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004371
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004372 free(curproxy->check_req);
4373 curproxy->check_req = (char *)calloc(1, reqlen);
4374 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004375
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004376 snprintf(curproxy->check_req, 4, "%c%c%c",
4377 ((unsigned char) packetlen & 0xff),
4378 ((unsigned char) (packetlen >> 8) & 0xff),
4379 ((unsigned char) (packetlen >> 16) & 0xff));
4380
4381 curproxy->check_req[3] = 1;
4382 curproxy->check_req[5] = 130;
4383 curproxy->check_req[11] = 1;
4384 curproxy->check_req[12] = 33;
4385 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4386 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4387 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4388 cur_arg += 3;
4389 } else {
4390 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4391 err_code |= ERR_ALERT | ERR_FATAL;
4392 goto out;
4393 }
4394 } else {
4395 packetlen = userlen + 7;
4396 reqlen = packetlen + 9;
4397
4398 free(curproxy->check_req);
4399 curproxy->check_req = (char *)calloc(1, reqlen);
4400 curproxy->check_len = reqlen;
4401
4402 snprintf(curproxy->check_req, 4, "%c%c%c",
4403 ((unsigned char) packetlen & 0xff),
4404 ((unsigned char) (packetlen >> 8) & 0xff),
4405 ((unsigned char) (packetlen >> 16) & 0xff));
4406
4407 curproxy->check_req[3] = 1;
4408 curproxy->check_req[5] = 128;
4409 curproxy->check_req[8] = 1;
4410 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4411 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4412 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4413 cur_arg += 2;
4414 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004415 } else {
4416 /* unknown suboption - catchall */
4417 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4418 file, linenum, args[0], args[1]);
4419 err_code |= ERR_ALERT | ERR_FATAL;
4420 goto out;
4421 }
4422 } /* end while loop */
4423 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004424 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004425 else if (!strcmp(args[1], "ldap-check")) {
4426 /* use LDAP request to check servers' health */
4427 free(curproxy->check_req);
4428 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004429 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004430 curproxy->options2 |= PR_O2_LDAP_CHK;
4431
4432 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4433 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4434 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4435 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004436 else if (!strcmp(args[1], "tcp-check")) {
4437 /* use raw TCPCHK send/expect to check servers' health */
4438 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4439 err_code |= ERR_WARN;
4440
4441 free(curproxy->check_req);
4442 curproxy->check_req = NULL;
4443 curproxy->options2 &= ~PR_O2_CHK_ANY;
4444 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4445 }
Simon Horman98637e52014-06-20 12:30:16 +09004446 else if (!strcmp(args[1], "external-check")) {
4447 /* excute an external command to check servers' health */
4448 free(curproxy->check_req);
4449 curproxy->check_req = NULL;
4450 curproxy->options2 &= ~PR_O2_CHK_ANY;
4451 curproxy->options2 |= PR_O2_EXT_CHK;
4452 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004453 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004454 int cur_arg;
4455
4456 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4457 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004458 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004459
Willy Tarreau87cf5142011-08-19 22:57:24 +02004460 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004461
4462 free(curproxy->fwdfor_hdr_name);
4463 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4464 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4465
4466 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4467 cur_arg = 2;
4468 while (*(args[cur_arg])) {
4469 if (!strcmp(args[cur_arg], "except")) {
4470 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004471 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004472 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4473 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004474 err_code |= ERR_ALERT | ERR_FATAL;
4475 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004476 }
4477 /* flush useless bits */
4478 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004479 cur_arg += 2;
4480 } else if (!strcmp(args[cur_arg], "header")) {
4481 /* suboption header - needs additional argument for it */
4482 if (*(args[cur_arg+1]) == 0) {
4483 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4484 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004485 err_code |= ERR_ALERT | ERR_FATAL;
4486 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004487 }
4488 free(curproxy->fwdfor_hdr_name);
4489 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4490 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4491 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004492 } else if (!strcmp(args[cur_arg], "if-none")) {
4493 curproxy->options &= ~PR_O_FF_ALWAYS;
4494 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004495 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004496 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004497 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004498 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004499 err_code |= ERR_ALERT | ERR_FATAL;
4500 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004501 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004502 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004503 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004504 else if (!strcmp(args[1], "originalto")) {
4505 int cur_arg;
4506
4507 /* insert x-original-to field, but not for the IP address listed as an except.
4508 * set default options (ie: bitfield, header name, etc)
4509 */
4510
4511 curproxy->options |= PR_O_ORGTO;
4512
4513 free(curproxy->orgto_hdr_name);
4514 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4515 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4516
Willy Tarreau87cf5142011-08-19 22:57:24 +02004517 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004518 cur_arg = 2;
4519 while (*(args[cur_arg])) {
4520 if (!strcmp(args[cur_arg], "except")) {
4521 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004522 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 +02004523 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4524 file, linenum, args[0], args[1], args[cur_arg]);
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 /* flush useless bits */
4529 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4530 cur_arg += 2;
4531 } else if (!strcmp(args[cur_arg], "header")) {
4532 /* suboption header - needs additional argument for it */
4533 if (*(args[cur_arg+1]) == 0) {
4534 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4535 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004536 err_code |= ERR_ALERT | ERR_FATAL;
4537 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004538 }
4539 free(curproxy->orgto_hdr_name);
4540 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4541 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4542 cur_arg += 2;
4543 } else {
4544 /* unknown suboption - catchall */
4545 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4546 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004547 err_code |= ERR_ALERT | ERR_FATAL;
4548 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004549 }
4550 } /* end while loop */
4551 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004552 else {
4553 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004554 err_code |= ERR_ALERT | ERR_FATAL;
4555 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004556 }
Willy Tarreau93893792009-07-23 13:19:11 +02004557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004558 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004559 else if (!strcmp(args[0], "default_backend")) {
4560 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004561 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004562
4563 if (*(args[1]) == 0) {
4564 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004565 err_code |= ERR_ALERT | ERR_FATAL;
4566 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004567 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004568 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004569 curproxy->defbe.name = strdup(args[1]);
4570 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004571 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004572 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004573 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004574
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004575 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4576 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 +01004577 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004578 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004579 /* enable reconnections to dispatch */
4580 curproxy->options |= PR_O_REDISP;
4581 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004582 else if (!strcmp(args[0], "http-check")) {
4583 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004584 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004585
4586 if (strcmp(args[1], "disable-on-404") == 0) {
4587 /* enable a graceful server shutdown on an HTTP 404 response */
4588 curproxy->options |= PR_O_DISABLE404;
4589 }
Willy Tarreauef781042010-01-27 11:53:01 +01004590 else if (strcmp(args[1], "send-state") == 0) {
4591 /* enable emission of the apparent state of a server in HTTP checks */
4592 curproxy->options2 |= PR_O2_CHK_SNDST;
4593 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004594 else if (strcmp(args[1], "expect") == 0) {
4595 const char *ptr_arg;
4596 int cur_arg;
4597
4598 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4599 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4600 err_code |= ERR_ALERT | ERR_FATAL;
4601 goto out;
4602 }
4603
4604 cur_arg = 2;
4605 /* consider exclamation marks, sole or at the beginning of a word */
4606 while (*(ptr_arg = args[cur_arg])) {
4607 while (*ptr_arg == '!') {
4608 curproxy->options2 ^= PR_O2_EXP_INV;
4609 ptr_arg++;
4610 }
4611 if (*ptr_arg)
4612 break;
4613 cur_arg++;
4614 }
4615 /* now ptr_arg points to the beginning of a word past any possible
4616 * exclamation mark, and cur_arg is the argument which holds this word.
4617 */
4618 if (strcmp(ptr_arg, "status") == 0) {
4619 if (!*(args[cur_arg + 1])) {
4620 Alert("parsing [%s:%d] : '%s %s %s' expects <string> 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_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004626 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004627 curproxy->expect_str = strdup(args[cur_arg + 1]);
4628 }
4629 else if (strcmp(ptr_arg, "string") == 0) {
4630 if (!*(args[cur_arg + 1])) {
4631 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4632 file, linenum, args[0], args[1], ptr_arg);
4633 err_code |= ERR_ALERT | ERR_FATAL;
4634 goto out;
4635 }
4636 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004637 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004638 curproxy->expect_str = strdup(args[cur_arg + 1]);
4639 }
4640 else if (strcmp(ptr_arg, "rstatus") == 0) {
4641 if (!*(args[cur_arg + 1])) {
4642 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4643 file, linenum, args[0], args[1], ptr_arg);
4644 err_code |= ERR_ALERT | ERR_FATAL;
4645 goto out;
4646 }
4647 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004648 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004649 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004650 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004651 free(curproxy->expect_regex);
4652 curproxy->expect_regex = NULL;
4653 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004654 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004655 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4656 error = NULL;
4657 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4658 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4659 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4660 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004661 err_code |= ERR_ALERT | ERR_FATAL;
4662 goto out;
4663 }
4664 }
4665 else if (strcmp(ptr_arg, "rstring") == 0) {
4666 if (!*(args[cur_arg + 1])) {
4667 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4668 file, linenum, args[0], args[1], ptr_arg);
4669 err_code |= ERR_ALERT | ERR_FATAL;
4670 goto out;
4671 }
4672 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004673 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004674 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004675 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004676 free(curproxy->expect_regex);
4677 curproxy->expect_regex = NULL;
4678 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004679 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004680 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4681 error = NULL;
4682 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4683 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4684 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4685 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004686 err_code |= ERR_ALERT | ERR_FATAL;
4687 goto out;
4688 }
4689 }
4690 else {
4691 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4692 file, linenum, args[0], args[1], ptr_arg);
4693 err_code |= ERR_ALERT | ERR_FATAL;
4694 goto out;
4695 }
4696 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004697 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004698 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 +02004699 err_code |= ERR_ALERT | ERR_FATAL;
4700 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004701 }
4702 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004703 else if (!strcmp(args[0], "tcp-check")) {
4704 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4705 err_code |= ERR_WARN;
4706
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004707 if (strcmp(args[1], "comment") == 0) {
4708 int cur_arg;
4709 struct tcpcheck_rule *tcpcheck;
4710
4711 cur_arg = 1;
4712 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4713 tcpcheck->action = TCPCHK_ACT_COMMENT;
4714
4715 if (!*args[cur_arg + 1]) {
4716 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4717 file, linenum, args[cur_arg]);
4718 err_code |= ERR_ALERT | ERR_FATAL;
4719 goto out;
4720 }
4721
4722 tcpcheck->comment = strdup(args[cur_arg + 1]);
4723
4724 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4725 }
4726 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004727 const char *ptr_arg;
4728 int cur_arg;
4729 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004730
4731 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02004732 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
4733 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
4734 tcpcheck->action == TCPCHK_ACT_COMMENT) {
4735 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
4736 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004737
Willy Tarreau5581c272015-05-13 12:24:53 +02004738 if (&tcpcheck->list != &curproxy->tcpcheck_rules
4739 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4740 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4741 file, linenum);
4742 err_code |= ERR_ALERT | ERR_FATAL;
4743 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004744 }
4745
4746 cur_arg = 2;
4747 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4748 tcpcheck->action = TCPCHK_ACT_CONNECT;
4749
4750 /* parsing each parameters to fill up the rule */
4751 while (*(ptr_arg = args[cur_arg])) {
4752 /* tcp port */
4753 if (strcmp(args[cur_arg], "port") == 0) {
4754 if ( (atol(args[cur_arg + 1]) > 65535) ||
4755 (atol(args[cur_arg + 1]) < 1) ){
4756 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4757 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4758 err_code |= ERR_ALERT | ERR_FATAL;
4759 goto out;
4760 }
4761 tcpcheck->port = atol(args[cur_arg + 1]);
4762 cur_arg += 2;
4763 }
4764 /* send proxy protocol */
4765 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4766 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4767 cur_arg++;
4768 }
4769#ifdef USE_OPENSSL
4770 else if (strcmp(args[cur_arg], "ssl") == 0) {
4771 curproxy->options |= PR_O_TCPCHK_SSL;
4772 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4773 cur_arg++;
4774 }
4775#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004776 /* comment for this tcpcheck line */
4777 else if (strcmp(args[cur_arg], "comment") == 0) {
4778 if (!*args[cur_arg + 1]) {
4779 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4780 file, linenum, args[cur_arg]);
4781 err_code |= ERR_ALERT | ERR_FATAL;
4782 goto out;
4783 }
4784 tcpcheck->comment = strdup(args[cur_arg + 1]);
4785 cur_arg += 2;
4786 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004787 else {
4788#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004789 Alert("parsing [%s:%d] : '%s %s' expects 'comment', 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004790#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004791 Alert("parsing [%s:%d] : '%s %s' expects 'comment', 'port', 'send-proxy' or but got '%s' as argument.\n",
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004792#endif /* USE_OPENSSL */
4793 file, linenum, args[0], args[1], args[cur_arg]);
4794 err_code |= ERR_ALERT | ERR_FATAL;
4795 goto out;
4796 }
4797
4798 }
4799
4800 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4801 }
4802 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004803 if (! *(args[2]) ) {
4804 /* SEND string expected */
4805 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4806 file, linenum, args[0], args[1], args[2]);
4807 err_code |= ERR_ALERT | ERR_FATAL;
4808 goto out;
4809 } else {
4810 struct tcpcheck_rule *tcpcheck;
4811
4812 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4813
4814 tcpcheck->action = TCPCHK_ACT_SEND;
4815 tcpcheck->string_len = strlen(args[2]);
4816 tcpcheck->string = strdup(args[2]);
4817 tcpcheck->expect_regex = NULL;
4818
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004819 /* comment for this tcpcheck line */
4820 if (strcmp(args[3], "comment") == 0) {
4821 if (!*args[4]) {
4822 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4823 file, linenum, args[3]);
4824 err_code |= ERR_ALERT | ERR_FATAL;
4825 goto out;
4826 }
4827 tcpcheck->comment = strdup(args[4]);
4828 }
4829
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004830 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4831 }
4832 }
4833 else if (strcmp(args[1], "send-binary") == 0) {
4834 if (! *(args[2]) ) {
4835 /* SEND binary string expected */
4836 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4837 file, linenum, args[0], args[1], args[2]);
4838 err_code |= ERR_ALERT | ERR_FATAL;
4839 goto out;
4840 } else {
4841 struct tcpcheck_rule *tcpcheck;
4842 char *err = NULL;
4843
4844 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4845
4846 tcpcheck->action = TCPCHK_ACT_SEND;
4847 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4848 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4849 file, linenum, args[0], args[1], args[2], err);
4850 err_code |= ERR_ALERT | ERR_FATAL;
4851 goto out;
4852 }
4853 tcpcheck->expect_regex = NULL;
4854
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004855 /* comment for this tcpcheck line */
4856 if (strcmp(args[3], "comment") == 0) {
4857 if (!*args[4]) {
4858 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4859 file, linenum, args[3]);
4860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
4862 }
4863 tcpcheck->comment = strdup(args[4]);
4864 }
4865
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004866 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4867 }
4868 }
4869 else if (strcmp(args[1], "expect") == 0) {
4870 const char *ptr_arg;
4871 int cur_arg;
4872 int inverse = 0;
4873
4874 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4875 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4876 err_code |= ERR_ALERT | ERR_FATAL;
4877 goto out;
4878 }
4879
4880 cur_arg = 2;
4881 /* consider exclamation marks, sole or at the beginning of a word */
4882 while (*(ptr_arg = args[cur_arg])) {
4883 while (*ptr_arg == '!') {
4884 inverse = !inverse;
4885 ptr_arg++;
4886 }
4887 if (*ptr_arg)
4888 break;
4889 cur_arg++;
4890 }
4891 /* now ptr_arg points to the beginning of a word past any possible
4892 * exclamation mark, and cur_arg is the argument which holds this word.
4893 */
4894 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004895 struct tcpcheck_rule *tcpcheck;
4896 char *err = NULL;
4897
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004898 if (!*(args[cur_arg + 1])) {
4899 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4900 file, linenum, args[0], args[1], ptr_arg);
4901 err_code |= ERR_ALERT | ERR_FATAL;
4902 goto out;
4903 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004904
4905 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4906
4907 tcpcheck->action = TCPCHK_ACT_EXPECT;
4908 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4909 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4910 file, linenum, args[0], args[1], args[2], err);
4911 err_code |= ERR_ALERT | ERR_FATAL;
4912 goto out;
4913 }
4914 tcpcheck->expect_regex = NULL;
4915 tcpcheck->inverse = inverse;
4916
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004917 /* tcpcheck comment */
4918 cur_arg += 2;
4919 if (strcmp(args[cur_arg], "comment") == 0) {
4920 if (!*args[cur_arg + 1]) {
4921 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4922 file, linenum, args[cur_arg + 1]);
4923 err_code |= ERR_ALERT | ERR_FATAL;
4924 goto out;
4925 }
4926 tcpcheck->comment = strdup(args[cur_arg + 1]);
4927 }
4928
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004929 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4930 }
4931 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004932 struct tcpcheck_rule *tcpcheck;
4933
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004934 if (!*(args[cur_arg + 1])) {
4935 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4936 file, linenum, args[0], args[1], ptr_arg);
4937 err_code |= ERR_ALERT | ERR_FATAL;
4938 goto out;
4939 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004940
4941 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4942
4943 tcpcheck->action = TCPCHK_ACT_EXPECT;
4944 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4945 tcpcheck->string = strdup(args[cur_arg + 1]);
4946 tcpcheck->expect_regex = NULL;
4947 tcpcheck->inverse = inverse;
4948
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004949 /* tcpcheck comment */
4950 cur_arg += 2;
4951 if (strcmp(args[cur_arg], "comment") == 0) {
4952 if (!*args[cur_arg + 1]) {
4953 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4954 file, linenum, args[cur_arg + 1]);
4955 err_code |= ERR_ALERT | ERR_FATAL;
4956 goto out;
4957 }
4958 tcpcheck->comment = strdup(args[cur_arg + 1]);
4959 }
4960
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004961 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4962 }
4963 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004964 struct tcpcheck_rule *tcpcheck;
4965
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004966 if (!*(args[cur_arg + 1])) {
4967 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4968 file, linenum, args[0], args[1], ptr_arg);
4969 err_code |= ERR_ALERT | ERR_FATAL;
4970 goto out;
4971 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004972
4973 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4974
4975 tcpcheck->action = TCPCHK_ACT_EXPECT;
4976 tcpcheck->string_len = 0;
4977 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004978 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4979 error = NULL;
4980 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4981 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4982 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4983 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004984 err_code |= ERR_ALERT | ERR_FATAL;
4985 goto out;
4986 }
4987 tcpcheck->inverse = inverse;
4988
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004989 /* tcpcheck comment */
4990 cur_arg += 2;
4991 if (strcmp(args[cur_arg], "comment") == 0) {
4992 if (!*args[cur_arg + 1]) {
4993 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4994 file, linenum, args[cur_arg + 1]);
4995 err_code |= ERR_ALERT | ERR_FATAL;
4996 goto out;
4997 }
4998 tcpcheck->comment = strdup(args[cur_arg + 1]);
4999 }
5000
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005001 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5002 }
5003 else {
5004 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5005 file, linenum, args[0], args[1], ptr_arg);
5006 err_code |= ERR_ALERT | ERR_FATAL;
5007 goto out;
5008 }
5009 }
5010 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005011 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005012 err_code |= ERR_ALERT | ERR_FATAL;
5013 goto out;
5014 }
5015 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005016 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005017 if (curproxy == &defproxy) {
5018 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005019 err_code |= ERR_ALERT | ERR_FATAL;
5020 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005021 }
5022
Willy Tarreaub80c2302007-11-30 20:51:32 +01005023 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005024 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005025
5026 if (strcmp(args[1], "fail") == 0) {
5027 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005028 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005029 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5030 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005031 err_code |= ERR_ALERT | ERR_FATAL;
5032 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005033 }
5034
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005035 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5036 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5037 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005038 err_code |= ERR_ALERT | ERR_FATAL;
5039 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005040 }
5041 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5042 }
5043 else {
5044 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005045 err_code |= ERR_ALERT | ERR_FATAL;
5046 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005047 }
5048 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005049#ifdef TPROXY
5050 else if (!strcmp(args[0], "transparent")) {
5051 /* enable transparent proxy connections */
5052 curproxy->options |= PR_O_TRANSP;
5053 }
5054#endif
5055 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005056 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005057 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005058
Willy Tarreaubaaee002006-06-26 02:48:02 +02005059 if (*(args[1]) == 0) {
5060 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005061 err_code |= ERR_ALERT | ERR_FATAL;
5062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005063 }
5064 curproxy->maxconn = atol(args[1]);
5065 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005066 else if (!strcmp(args[0], "backlog")) { /* backlog */
5067 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005068 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005069
5070 if (*(args[1]) == 0) {
5071 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005072 err_code |= ERR_ALERT | ERR_FATAL;
5073 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005074 }
5075 curproxy->backlog = atol(args[1]);
5076 }
Willy Tarreau86034312006-12-29 00:10:33 +01005077 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005078 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005079 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005080
Willy Tarreau86034312006-12-29 00:10:33 +01005081 if (*(args[1]) == 0) {
5082 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005083 err_code |= ERR_ALERT | ERR_FATAL;
5084 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005085 }
5086 curproxy->fullconn = atol(args[1]);
5087 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005088 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5089 if (*(args[1]) == 0) {
5090 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005091 err_code |= ERR_ALERT | ERR_FATAL;
5092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005093 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005094 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5095 if (err) {
5096 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5097 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005098 err_code |= ERR_ALERT | ERR_FATAL;
5099 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005100 }
5101 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 }
5103 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005104 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005105 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005106 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005107
Willy Tarreaubaaee002006-06-26 02:48:02 +02005108 if (curproxy == &defproxy) {
5109 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005110 err_code |= ERR_ALERT | ERR_FATAL;
5111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005112 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005113 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005114 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005115
Willy Tarreau902636f2013-03-10 19:44:48 +01005116 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005117 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005118 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005119 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005120 goto out;
5121 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005122
5123 proto = protocol_by_family(sk->ss_family);
5124 if (!proto || !proto->connect) {
5125 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5126 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005127 err_code |= ERR_ALERT | ERR_FATAL;
5128 goto out;
5129 }
5130
5131 if (port1 != port2) {
5132 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5133 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005134 err_code |= ERR_ALERT | ERR_FATAL;
5135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005136 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005137
5138 if (!port1) {
5139 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5140 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005141 err_code |= ERR_ALERT | ERR_FATAL;
5142 goto out;
5143 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005144
Willy Tarreaud5191e72010-02-09 20:50:45 +01005145 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005146 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 }
5148 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005149 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005150 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005151
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005152 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5153 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005156 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005158 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005159 /**
5160 * The syntax for hash-type config element is
5161 * hash-type {map-based|consistent} [[<algo>] avalanche]
5162 *
5163 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5164 */
5165 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005166
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005167 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5168 err_code |= ERR_WARN;
5169
5170 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005171 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5172 }
5173 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005174 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5175 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005176 else if (strcmp(args[1], "avalanche") == 0) {
5177 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]);
5178 err_code |= ERR_ALERT | ERR_FATAL;
5179 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005180 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005181 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005182 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
5185 }
Bhaskar98634f02013-10-29 23:30:51 -04005186
5187 /* set the hash function to use */
5188 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005189 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005190 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005191
5192 /* if consistent with no argument, then avalanche modifier is also applied */
5193 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5194 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005195 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005196 /* set the hash function */
5197 if (!strcmp(args[2], "sdbm")) {
5198 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5199 }
5200 else if (!strcmp(args[2], "djb2")) {
5201 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005202 }
5203 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005204 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005205 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005206 else if (!strcmp(args[2], "crc32")) {
5207 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5208 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005209 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005210 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 -05005211 err_code |= ERR_ALERT | ERR_FATAL;
5212 goto out;
5213 }
5214
5215 /* set the hash modifier */
5216 if (!strcmp(args[3], "avalanche")) {
5217 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5218 }
5219 else if (*args[3]) {
5220 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
5223 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005224 }
William Lallemanda73203e2012-03-12 12:48:57 +01005225 }
William Lallemanda73203e2012-03-12 12:48:57 +01005226 else if (strcmp(args[0], "unique-id-format") == 0) {
5227 if (!*(args[1])) {
5228 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5229 err_code |= ERR_ALERT | ERR_FATAL;
5230 goto out;
5231 }
William Lallemand3203ff42012-11-11 17:30:56 +01005232 if (*(args[2])) {
5233 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5234 err_code |= ERR_ALERT | ERR_FATAL;
5235 goto out;
5236 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005237 free(curproxy->conf.uniqueid_format_string);
5238 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005239
Willy Tarreau62a61232013-04-12 18:13:46 +02005240 free(curproxy->conf.uif_file);
5241 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5242 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005243 }
William Lallemanda73203e2012-03-12 12:48:57 +01005244
5245 else if (strcmp(args[0], "unique-id-header") == 0) {
5246 if (!*(args[1])) {
5247 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5248 err_code |= ERR_ALERT | ERR_FATAL;
5249 goto out;
5250 }
5251 free(curproxy->header_unique_id);
5252 curproxy->header_unique_id = strdup(args[1]);
5253 }
5254
William Lallemand723b73a2012-02-08 16:37:49 +01005255 else if (strcmp(args[0], "log-format") == 0) {
5256 if (!*(args[1])) {
5257 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5258 err_code |= ERR_ALERT | ERR_FATAL;
5259 goto out;
5260 }
William Lallemand3203ff42012-11-11 17:30:56 +01005261 if (*(args[2])) {
5262 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5263 err_code |= ERR_ALERT | ERR_FATAL;
5264 goto out;
5265 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005266
Willy Tarreau62a61232013-04-12 18:13:46 +02005267 if (curproxy->conf.logformat_string != default_http_log_format &&
5268 curproxy->conf.logformat_string != default_tcp_log_format &&
5269 curproxy->conf.logformat_string != clf_http_log_format)
5270 free(curproxy->conf.logformat_string);
5271 curproxy->conf.logformat_string = strdup(args[1]);
5272
5273 free(curproxy->conf.lfs_file);
5274 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5275 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005276
5277 /* get a chance to improve log-format error reporting by
5278 * reporting the correct line-number when possible.
5279 */
5280 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5281 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5282 file, linenum, curproxy->id);
5283 err_code |= ERR_WARN;
5284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005285 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005286 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5287 if (*(args[1]) == 0) {
5288 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5289 err_code |= ERR_ALERT | ERR_FATAL;
5290 goto out;
5291 }
5292 free(curproxy->log_tag);
5293 curproxy->log_tag = strdup(args[1]);
5294 }
William Lallemand0f99e342011-10-12 17:50:54 +02005295 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5296 /* delete previous herited or defined syslog servers */
5297 struct logsrv *back;
5298
5299 if (*(args[1]) != 0) {
5300 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5301 err_code |= ERR_ALERT | ERR_FATAL;
5302 goto out;
5303 }
5304
William Lallemand723b73a2012-02-08 16:37:49 +01005305 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5306 LIST_DEL(&tmplogsrv->list);
5307 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005308 }
5309 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005311 struct logsrv *logsrv;
5312
Willy Tarreaubaaee002006-06-26 02:48:02 +02005313 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005314 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005315 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005316 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005317 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005318 LIST_INIT(&node->list);
5319 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5320 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321 }
5322 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005323 struct sockaddr_storage *sk;
5324 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005325 int arg = 0;
5326 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005327
5328 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005329
Willy Tarreau18324f52014-06-27 18:10:07 +02005330 /* just after the address, a length may be specified */
5331 if (strcmp(args[arg+2], "len") == 0) {
5332 len = atoi(args[arg+3]);
5333 if (len < 80 || len > 65535) {
5334 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5335 file, linenum, args[arg+3]);
5336 err_code |= ERR_ALERT | ERR_FATAL;
5337 goto out;
5338 }
5339 logsrv->maxlen = len;
5340
5341 /* skip these two args */
5342 arg += 2;
5343 }
5344 else
5345 logsrv->maxlen = MAX_SYSLOG_LEN;
5346
5347 if (logsrv->maxlen > global.max_syslog_len) {
5348 global.max_syslog_len = logsrv->maxlen;
5349 logline = realloc(logline, global.max_syslog_len + 1);
5350 }
5351
5352 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005353 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005354 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005355 err_code |= ERR_ALERT | ERR_FATAL;
5356 goto out;
5357
Willy Tarreaubaaee002006-06-26 02:48:02 +02005358 }
5359
William Lallemand0f99e342011-10-12 17:50:54 +02005360 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005361 if (*(args[arg+3])) {
5362 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005363 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005364 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005365 err_code |= ERR_ALERT | ERR_FATAL;
5366 goto out;
5367
Willy Tarreaubaaee002006-06-26 02:48:02 +02005368 }
5369 }
5370
William Lallemand0f99e342011-10-12 17:50:54 +02005371 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005372 if (*(args[arg+4])) {
5373 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005374 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005375 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005376 err_code |= ERR_ALERT | ERR_FATAL;
5377 goto out;
5378
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005379 }
5380 }
5381
Willy Tarreau902636f2013-03-10 19:44:48 +01005382 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005383 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005384 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005385 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005386 goto out;
5387 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005388
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005389 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005390
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005391 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005392 if (port1 != port2) {
5393 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5394 file, linenum, args[0], args[1]);
5395 err_code |= ERR_ALERT | ERR_FATAL;
5396 goto out;
5397 }
5398
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005399 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005400 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005401 }
William Lallemand0f99e342011-10-12 17:50:54 +02005402
5403 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005404 }
5405 else {
5406 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5407 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005408 err_code |= ERR_ALERT | ERR_FATAL;
5409 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005410 }
5411 }
5412 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005413 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005414 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005415 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005416 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005417
Willy Tarreau977b8e42006-12-29 14:19:17 +01005418 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005419 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005420
Willy Tarreaubaaee002006-06-26 02:48:02 +02005421 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005422 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5423 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005424 err_code |= ERR_ALERT | ERR_FATAL;
5425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005426 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005427
5428 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005429 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5430 free(curproxy->conn_src.iface_name);
5431 curproxy->conn_src.iface_name = NULL;
5432 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005433
Willy Tarreau902636f2013-03-10 19:44:48 +01005434 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005435 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005436 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005437 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005438 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005439 goto out;
5440 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005441
5442 proto = protocol_by_family(sk->ss_family);
5443 if (!proto || !proto->connect) {
5444 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005445 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005446 err_code |= ERR_ALERT | ERR_FATAL;
5447 goto out;
5448 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005449
5450 if (port1 != port2) {
5451 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5452 file, linenum, args[0], args[1]);
5453 err_code |= ERR_ALERT | ERR_FATAL;
5454 goto out;
5455 }
5456
Willy Tarreauef9a3602012-12-08 22:29:20 +01005457 curproxy->conn_src.source_addr = *sk;
5458 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005459
5460 cur_arg = 2;
5461 while (*(args[cur_arg])) {
5462 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005463#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5464#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005465 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005466 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5467 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005468 err_code |= ERR_ALERT | ERR_FATAL;
5469 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005470 }
5471#endif
5472 if (!*args[cur_arg + 1]) {
5473 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5474 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005475 err_code |= ERR_ALERT | ERR_FATAL;
5476 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005477 }
5478
5479 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005480 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5481 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005482 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005483 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5484 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005485 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5486 char *name, *end;
5487
5488 name = args[cur_arg+1] + 7;
5489 while (isspace(*name))
5490 name++;
5491
5492 end = name;
5493 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5494 end++;
5495
Willy Tarreauef9a3602012-12-08 22:29:20 +01005496 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5497 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5498 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5499 curproxy->conn_src.bind_hdr_len = end - name;
5500 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5501 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5502 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005503
5504 /* now look for an occurrence number */
5505 while (isspace(*end))
5506 end++;
5507 if (*end == ',') {
5508 end++;
5509 name = end;
5510 if (*end == '-')
5511 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005512 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005513 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005514 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005515 }
5516
Willy Tarreauef9a3602012-12-08 22:29:20 +01005517 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005518 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5519 " occurrences values smaller than %d.\n",
5520 file, linenum, MAX_HDR_HISTORY);
5521 err_code |= ERR_ALERT | ERR_FATAL;
5522 goto out;
5523 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005524 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005525 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005526
Willy Tarreau902636f2013-03-10 19:44:48 +01005527 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005528 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005529 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005530 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005531 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005532 goto out;
5533 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005534
5535 proto = protocol_by_family(sk->ss_family);
5536 if (!proto || !proto->connect) {
5537 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5538 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005539 err_code |= ERR_ALERT | ERR_FATAL;
5540 goto out;
5541 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005542
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005543 if (port1 != port2) {
5544 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5545 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005546 err_code |= ERR_ALERT | ERR_FATAL;
5547 goto out;
5548 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005549 curproxy->conn_src.tproxy_addr = *sk;
5550 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005551 }
5552 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005553#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005554 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005555#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005556#else /* no TPROXY support */
5557 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005558 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005559 err_code |= ERR_ALERT | ERR_FATAL;
5560 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005561#endif
5562 cur_arg += 2;
5563 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005564 }
5565
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005566 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5567#ifdef SO_BINDTODEVICE
5568 if (!*args[cur_arg + 1]) {
5569 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5570 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005571 err_code |= ERR_ALERT | ERR_FATAL;
5572 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005573 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005574 free(curproxy->conn_src.iface_name);
5575 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5576 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005577 global.last_checks |= LSTCHK_NETADM;
5578#else
5579 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5580 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005581 err_code |= ERR_ALERT | ERR_FATAL;
5582 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005583#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005584 cur_arg += 2;
5585 continue;
5586 }
5587 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005588 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005589 err_code |= ERR_ALERT | ERR_FATAL;
5590 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005591 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005592 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005593 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5594 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5595 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005596 err_code |= ERR_ALERT | ERR_FATAL;
5597 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005598 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005599 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005600 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005601 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5602 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005603 err_code |= ERR_ALERT | ERR_FATAL;
5604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005606
5607 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005608 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005609 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005610 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005612 }
5613 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005614 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005615 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005616 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005617 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005619 }
5620 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005621 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005622 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005623 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005624 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005626 }
5627 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005628 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005629 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005630 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005631 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005633 }
5634 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005635 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005636 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005637 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005638 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005640 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005641 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005642 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005643 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005644 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005645 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005646 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005647 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005648 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005649 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005650 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005651 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005652 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005653 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005654
5655 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5656 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 +01005657 }
5658 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005659 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005660 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005661 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005662 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005663 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005664
5665 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5666 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 +01005667 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005668 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005669 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005670 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5671 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005672 err_code |= ERR_ALERT | ERR_FATAL;
5673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005674 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005675
5676 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005677 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005678 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005679 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005680 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005681 }
5682 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005683 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005684 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005685 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005686 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005688 }
5689 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005690 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005691 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005692 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005693 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005694 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005695 }
5696 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005697 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005698 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005699 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005700 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005702 }
5703 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005704 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005705 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005706 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005707 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005708 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005709 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005710 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005711 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005712 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005713 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005714 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005715 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005716 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005717 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005718 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005719
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720 if (curproxy == &defproxy) {
5721 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005722 err_code |= ERR_ALERT | ERR_FATAL;
5723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005725 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005726 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005727
Willy Tarreaubaaee002006-06-26 02:48:02 +02005728 if (*(args[1]) == 0) {
5729 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005730 err_code |= ERR_ALERT | ERR_FATAL;
5731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005732 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005733
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005734 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005735 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5736 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5737 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005738 err_code |= ERR_ALERT | ERR_FATAL;
5739 goto out;
5740 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005741 err_code |= warnif_cond_conflicts(cond,
5742 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5743 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005744 }
5745 else if (*args[2]) {
5746 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5747 file, linenum, args[0], args[2]);
5748 err_code |= ERR_ALERT | ERR_FATAL;
5749 goto out;
5750 }
5751
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005752 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005753 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005754 wl->s = strdup(args[1]);
5755 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005756 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005757 }
5758 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005759 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005760 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5761 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005762 err_code |= ERR_ALERT | ERR_FATAL;
5763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005764 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005765
Willy Tarreauade5ec42010-01-28 19:33:49 +01005766 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005767 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005768 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005769 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771 }
5772 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005773 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005774 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005775 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005776 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005778 }
5779 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005780 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005781 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005782 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005783 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005785 }
5786 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005787 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5789 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005790 err_code |= ERR_ALERT | ERR_FATAL;
5791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792 }
5793
Willy Tarreauade5ec42010-01-28 19:33:49 +01005794 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005795 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005796 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005797 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005799 }
5800 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005801 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005802 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005803 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005804 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005806 }
5807 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005808 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005809 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005810 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005811 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005813 }
5814 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005815 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005816
Willy Tarreaubaaee002006-06-26 02:48:02 +02005817 if (curproxy == &defproxy) {
5818 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005819 err_code |= ERR_ALERT | ERR_FATAL;
5820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005821 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005822 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005823 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005824
Willy Tarreaubaaee002006-06-26 02:48:02 +02005825 if (*(args[1]) == 0) {
5826 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005827 err_code |= ERR_ALERT | ERR_FATAL;
5828 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005829 }
5830
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005831 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005832 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5833 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5834 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005835 err_code |= ERR_ALERT | ERR_FATAL;
5836 goto out;
5837 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005838 err_code |= warnif_cond_conflicts(cond,
5839 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5840 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005841 }
5842 else if (*args[2]) {
5843 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5844 file, linenum, args[0], args[2]);
5845 err_code |= ERR_ALERT | ERR_FATAL;
5846 goto out;
5847 }
5848
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005849 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005850 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005851 wl->s = strdup(args[1]);
5852 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005853 }
5854 else if (!strcmp(args[0], "errorloc") ||
5855 !strcmp(args[0], "errorloc302") ||
5856 !strcmp(args[0], "errorloc303")) { /* error location */
5857 int errnum, errlen;
5858 char *err;
5859
Willy Tarreau977b8e42006-12-29 14:19:17 +01005860 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005861 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005862
Willy Tarreaubaaee002006-06-26 02:48:02 +02005863 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005864 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005865 err_code |= ERR_ALERT | ERR_FATAL;
5866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005867 }
5868
5869 errnum = atol(args[1]);
5870 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005871 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5872 err = malloc(errlen);
5873 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005874 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005875 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5876 err = malloc(errlen);
5877 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005878 }
5879
Willy Tarreau0f772532006-12-23 20:51:41 +01005880 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5881 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005882 chunk_destroy(&curproxy->errmsg[rc]);
5883 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005884 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005885 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005886 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005887
5888 if (rc >= HTTP_ERR_SIZE) {
5889 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5890 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 free(err);
5892 }
5893 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005894 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5895 int errnum, errlen, fd;
5896 char *err;
5897 struct stat stat;
5898
5899 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005900 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005901
5902 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005903 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005904 err_code |= ERR_ALERT | ERR_FATAL;
5905 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005906 }
5907
5908 fd = open(args[2], O_RDONLY);
5909 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5910 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5911 file, linenum, args[2], args[1]);
5912 if (fd >= 0)
5913 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005914 err_code |= ERR_ALERT | ERR_FATAL;
5915 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005916 }
5917
Willy Tarreau27a674e2009-08-17 07:23:33 +02005918 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005919 errlen = stat.st_size;
5920 } else {
5921 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005922 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005923 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005924 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005925 }
5926
5927 err = malloc(errlen); /* malloc() must succeed during parsing */
5928 errnum = read(fd, err, errlen);
5929 if (errnum != errlen) {
5930 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5931 file, linenum, args[2], args[1]);
5932 close(fd);
5933 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005934 err_code |= ERR_ALERT | ERR_FATAL;
5935 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005936 }
5937 close(fd);
5938
5939 errnum = atol(args[1]);
5940 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5941 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005942 chunk_destroy(&curproxy->errmsg[rc]);
5943 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005944 break;
5945 }
5946 }
5947
5948 if (rc >= HTTP_ERR_SIZE) {
5949 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5950 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005951 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005952 free(err);
5953 }
5954 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005955 else if (!strcmp(args[0], "compression")) {
5956 struct comp *comp;
5957 if (curproxy->comp == NULL) {
5958 comp = calloc(1, sizeof(struct comp));
5959 curproxy->comp = comp;
5960 } else {
5961 comp = curproxy->comp;
5962 }
5963
5964 if (!strcmp(args[1], "algo")) {
5965 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005966 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005967
William Lallemand82fe75c2012-10-23 10:25:10 +02005968 cur_arg = 2;
5969 if (!*args[cur_arg]) {
5970 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5971 file, linenum, args[0]);
5972 err_code |= ERR_ALERT | ERR_FATAL;
5973 goto out;
5974 }
5975 while (*(args[cur_arg])) {
5976 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5977 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5978 file, linenum, args[0], args[cur_arg]);
5979 err_code |= ERR_ALERT | ERR_FATAL;
5980 goto out;
5981 }
William Lallemand552df672012-11-07 13:21:47 +01005982 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5983 curproxy->comp->algos->end(&ctx);
5984 } else {
5985 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5986 file, linenum, args[0], args[cur_arg]);
5987 err_code |= ERR_ALERT | ERR_FATAL;
5988 goto out;
5989 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005990 cur_arg ++;
5991 continue;
5992 }
5993 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005994 else if (!strcmp(args[1], "offload")) {
5995 comp->offload = 1;
5996 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005997 else if (!strcmp(args[1], "type")) {
5998 int cur_arg;
5999 cur_arg = 2;
6000 if (!*args[cur_arg]) {
6001 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6002 file, linenum, args[0]);
6003 err_code |= ERR_ALERT | ERR_FATAL;
6004 goto out;
6005 }
6006 while (*(args[cur_arg])) {
6007 comp_append_type(comp, args[cur_arg]);
6008 cur_arg ++;
6009 continue;
6010 }
6011 }
6012 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006013 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006014 file, linenum, args[0]);
6015 err_code |= ERR_ALERT | ERR_FATAL;
6016 goto out;
6017 }
6018 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006019 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006020 struct cfg_kw_list *kwl;
6021 int index;
6022
6023 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6024 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6025 if (kwl->kw[index].section != CFG_LISTEN)
6026 continue;
6027 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6028 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006029 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006030 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006031 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006032 err_code |= ERR_ALERT | ERR_FATAL;
6033 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006034 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006035 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006036 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006037 err_code |= ERR_WARN;
6038 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006039 }
Willy Tarreau93893792009-07-23 13:19:11 +02006040 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006041 }
6042 }
6043 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006044
Willy Tarreau6daf3432008-01-22 16:44:08 +01006045 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006046 err_code |= ERR_ALERT | ERR_FATAL;
6047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006048 }
Willy Tarreau93893792009-07-23 13:19:11 +02006049 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006050 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006051 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006052}
6053
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006054int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006055cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6056{
6057#ifdef CONFIG_HAP_NS
6058 const char *err;
6059 const char *item = args[0];
6060
6061 if (!strcmp(item, "namespace_list")) {
6062 return 0;
6063 }
6064 else if (!strcmp(item, "namespace")) {
6065 size_t idx = 1;
6066 const char *current;
6067 while (*(current = args[idx++])) {
6068 err = invalid_char(current);
6069 if (err) {
6070 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6071 file, linenum, *err, item, current);
6072 return ERR_ALERT | ERR_FATAL;
6073 }
6074
6075 if (netns_store_lookup(current, strlen(current))) {
6076 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6077 file, linenum, current);
6078 return ERR_ALERT | ERR_FATAL;
6079 }
6080 if (!netns_store_insert(current)) {
6081 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6082 file, linenum, current);
6083 return ERR_ALERT | ERR_FATAL;
6084 }
6085 }
6086 }
6087
6088 return 0;
6089#else
6090 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6091 file, linenum);
6092 return ERR_ALERT | ERR_FATAL;
6093#endif
6094}
6095
6096int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006097cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6098{
6099
6100 int err_code = 0;
6101 const char *err;
6102
6103 if (!strcmp(args[0], "userlist")) { /* new userlist */
6104 struct userlist *newul;
6105
6106 if (!*args[1]) {
6107 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6108 file, linenum, args[0]);
6109 err_code |= ERR_ALERT | ERR_FATAL;
6110 goto out;
6111 }
6112
6113 err = invalid_char(args[1]);
6114 if (err) {
6115 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6116 file, linenum, *err, args[0], args[1]);
6117 err_code |= ERR_ALERT | ERR_FATAL;
6118 goto out;
6119 }
6120
6121 for (newul = userlist; newul; newul = newul->next)
6122 if (!strcmp(newul->name, args[1])) {
6123 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6124 file, linenum, args[1]);
6125 err_code |= ERR_WARN;
6126 goto out;
6127 }
6128
6129 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6130 if (!newul) {
6131 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6132 err_code |= ERR_ALERT | ERR_ABORT;
6133 goto out;
6134 }
6135
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006136 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006137 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006138 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6139 err_code |= ERR_ALERT | ERR_ABORT;
6140 goto out;
6141 }
6142
6143 newul->next = userlist;
6144 userlist = newul;
6145
6146 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006147 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006148 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006149 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006150
6151 if (!*args[1]) {
6152 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6153 file, linenum, args[0]);
6154 err_code |= ERR_ALERT | ERR_FATAL;
6155 goto out;
6156 }
6157
6158 err = invalid_char(args[1]);
6159 if (err) {
6160 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6161 file, linenum, *err, args[0], args[1]);
6162 err_code |= ERR_ALERT | ERR_FATAL;
6163 goto out;
6164 }
6165
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006166 for (ag = userlist->groups; ag; ag = ag->next)
6167 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006168 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6169 file, linenum, args[1], userlist->name);
6170 err_code |= ERR_ALERT;
6171 goto out;
6172 }
6173
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006174 ag = calloc(1, sizeof(*ag));
6175 if (!ag) {
6176 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6177 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006178 goto out;
6179 }
6180
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006181 ag->name = strdup(args[1]);
6182 if (!ag) {
6183 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6184 err_code |= ERR_ALERT | ERR_ABORT;
6185 goto out;
6186 }
6187
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006188 cur_arg = 2;
6189
6190 while (*args[cur_arg]) {
6191 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006192 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006193 cur_arg += 2;
6194 continue;
6195 } else {
6196 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6197 file, linenum, args[0]);
6198 err_code |= ERR_ALERT | ERR_FATAL;
6199 goto out;
6200 }
6201 }
6202
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006203 ag->next = userlist->groups;
6204 userlist->groups = ag;
6205
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006206 } else if (!strcmp(args[0], "user")) { /* new user */
6207 struct auth_users *newuser;
6208 int cur_arg;
6209
6210 if (!*args[1]) {
6211 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6212 file, linenum, args[0]);
6213 err_code |= ERR_ALERT | ERR_FATAL;
6214 goto out;
6215 }
6216
6217 for (newuser = userlist->users; newuser; newuser = newuser->next)
6218 if (!strcmp(newuser->user, args[1])) {
6219 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6220 file, linenum, args[1], userlist->name);
6221 err_code |= ERR_ALERT;
6222 goto out;
6223 }
6224
6225 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6226 if (!newuser) {
6227 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6228 err_code |= ERR_ALERT | ERR_ABORT;
6229 goto out;
6230 }
6231
6232 newuser->user = strdup(args[1]);
6233
6234 newuser->next = userlist->users;
6235 userlist->users = newuser;
6236
6237 cur_arg = 2;
6238
6239 while (*args[cur_arg]) {
6240 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006241#ifdef CONFIG_HAP_CRYPT
6242 if (!crypt("", args[cur_arg + 1])) {
6243 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6244 file, linenum, newuser->user);
6245 err_code |= ERR_ALERT | ERR_FATAL;
6246 goto out;
6247 }
6248#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006249 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6250 file, linenum);
6251 err_code |= ERR_ALERT;
6252#endif
6253 newuser->pass = strdup(args[cur_arg + 1]);
6254 cur_arg += 2;
6255 continue;
6256 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6257 newuser->pass = strdup(args[cur_arg + 1]);
6258 newuser->flags |= AU_O_INSECURE;
6259 cur_arg += 2;
6260 continue;
6261 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006262 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006263 cur_arg += 2;
6264 continue;
6265 } else {
6266 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6267 file, linenum, args[0]);
6268 err_code |= ERR_ALERT | ERR_FATAL;
6269 goto out;
6270 }
6271 }
6272 } else {
6273 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6274 err_code |= ERR_ALERT | ERR_FATAL;
6275 }
6276
6277out:
6278 return err_code;
6279}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006280
6281/*
6282 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006283 * Returns the error code, 0 if OK, or any combination of :
6284 * - ERR_ABORT: must abort ASAP
6285 * - ERR_FATAL: we can continue parsing but not start the service
6286 * - ERR_WARN: a warning has been emitted
6287 * - ERR_ALERT: an alert has been emitted
6288 * Only the two first ones can stop processing, the two others are just
6289 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006290 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006291int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006292{
William Lallemand64e84512015-05-12 14:25:37 +02006293 char *thisline;
6294 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006295 FILE *f;
6296 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006297 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006298 struct cfg_section *cs = NULL;
6299 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006300 int readbytes = 0;
6301
6302 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006303 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006304 return -1;
6305 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006306
6307 /* Register internal sections */
6308 if (!cfg_register_section("listen", cfg_parse_listen) ||
6309 !cfg_register_section("frontend", cfg_parse_listen) ||
6310 !cfg_register_section("backend", cfg_parse_listen) ||
6311 !cfg_register_section("ruleset", cfg_parse_listen) ||
6312 !cfg_register_section("defaults", cfg_parse_listen) ||
6313 !cfg_register_section("global", cfg_parse_global) ||
6314 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006315 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006316 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006317 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006318 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006319
Willy Tarreaubaaee002006-06-26 02:48:02 +02006320 if ((f=fopen(file,"r")) == NULL)
6321 return -1;
6322
William Lallemandb2f07452015-05-12 14:27:13 +02006323next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006324 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006325 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006326 char *end;
6327 char *args[MAX_LINE_ARGS + 1];
6328 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006329 int dquote = 0; /* double quote */
6330 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006331
Willy Tarreaubaaee002006-06-26 02:48:02 +02006332 linenum++;
6333
6334 end = line + strlen(line);
6335
William Lallemand64e84512015-05-12 14:25:37 +02006336 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006337 /* Check if we reached the limit and the last char is not \n.
6338 * Watch out for the last line without the terminating '\n'!
6339 */
William Lallemand64e84512015-05-12 14:25:37 +02006340 char *newline;
6341 int newlinesize = linesize * 2;
6342
6343 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6344 if (newline == NULL) {
6345 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6346 file, linenum);
6347 err_code |= ERR_ALERT | ERR_FATAL;
6348 continue;
6349 }
6350
6351 readbytes = linesize - 1;
6352 linesize = newlinesize;
6353 thisline = newline;
6354 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006355 }
6356
William Lallemand64e84512015-05-12 14:25:37 +02006357 readbytes = 0;
6358
Willy Tarreaubaaee002006-06-26 02:48:02 +02006359 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006360 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006361 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006362
Willy Tarreaubaaee002006-06-26 02:48:02 +02006363 arg = 0;
6364 args[arg] = line;
6365
6366 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006367 if (*line == '"' && !squote) { /* double quote outside single quotes */
6368 if (dquote)
6369 dquote = 0;
6370 else
6371 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006372 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006373 end--;
6374 }
6375 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6376 if (squote)
6377 squote = 0;
6378 else
6379 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006380 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006381 end--;
6382 }
6383 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006384 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6385 * C equivalent value. Other combinations left unchanged (eg: \1).
6386 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006387 int skip = 0;
6388 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6389 *line = line[1];
6390 skip = 1;
6391 }
6392 else if (line[1] == 'r') {
6393 *line = '\r';
6394 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006395 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006396 else if (line[1] == 'n') {
6397 *line = '\n';
6398 skip = 1;
6399 }
6400 else if (line[1] == 't') {
6401 *line = '\t';
6402 skip = 1;
6403 }
6404 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006405 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006406 unsigned char hex1, hex2;
6407 hex1 = toupper(line[2]) - '0';
6408 hex2 = toupper(line[3]) - '0';
6409 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6410 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6411 *line = (hex1<<4) + hex2;
6412 skip = 3;
6413 }
6414 else {
6415 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006416 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006417 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006418 } else if (line[1] == '"') {
6419 *line = '"';
6420 skip = 1;
6421 } else if (line[1] == '\'') {
6422 *line = '\'';
6423 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006424 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6425 *line = '$';
6426 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006427 }
6428 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006429 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006430 end -= skip;
6431 }
6432 line++;
6433 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006434 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006435 /* end of string, end of loop */
6436 *line = 0;
6437 break;
6438 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006439 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006440 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006441 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006442 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006443 line++;
6444 args[++arg] = line;
6445 }
William Lallemandb2f07452015-05-12 14:27:13 +02006446 else if (dquote && *line == '$') {
6447 /* environment variables are evaluated inside double quotes */
6448 char *var_beg;
6449 char *var_end;
6450 char save_char;
6451 char *value;
6452 int val_len;
6453 int newlinesize;
6454 int braces = 0;
6455
6456 var_beg = line + 1;
6457 var_end = var_beg;
6458
6459 if (*var_beg == '{') {
6460 var_beg++;
6461 var_end++;
6462 braces = 1;
6463 }
6464
6465 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6466 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6467 err_code |= ERR_ALERT | ERR_FATAL;
6468 goto next_line; /* skip current line */
6469 }
6470
6471 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6472 var_end++;
6473
6474 save_char = *var_end;
6475 *var_end = '\0';
6476 value = getenv(var_beg);
6477 *var_end = save_char;
6478 val_len = value ? strlen(value) : 0;
6479
6480 if (braces) {
6481 if (*var_end == '}') {
6482 var_end++;
6483 braces = 0;
6484 } else {
6485 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
6486 err_code |= ERR_ALERT | ERR_FATAL;
6487 goto next_line; /* skip current line */
6488 }
6489 }
6490
6491 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
6492
6493 /* if not enough space in thisline */
6494 if (newlinesize > linesize) {
6495 char *newline;
6496
6497 newline = realloc(thisline, newlinesize * sizeof(*thisline));
6498 if (newline == NULL) {
6499 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
6500 err_code |= ERR_ALERT | ERR_FATAL;
6501 goto next_line; /* slip current line */
6502 }
6503 /* recompute pointers if realloc returns a new pointer */
6504 if (newline != thisline) {
6505 int i;
6506 int diff;
6507
6508 for (i = 0; i <= arg; i++) {
6509 diff = args[i] - thisline;
6510 args[i] = newline + diff;
6511 }
6512
6513 diff = var_end - thisline;
6514 var_end = newline + diff;
6515 diff = end - thisline;
6516 end = newline + diff;
6517 diff = line - thisline;
6518 line = newline + diff;
6519 thisline = newline;
6520 }
6521 linesize = newlinesize;
6522 }
6523
6524 /* insert value inside the line */
6525 memmove(line + val_len, var_end, end - var_end + 1);
6526 memcpy(line, value, val_len);
6527 end += val_len - (var_end - line);
6528 line += val_len;
6529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006530 else {
6531 line++;
6532 }
6533 }
William Lallemandb2f07452015-05-12 14:27:13 +02006534
William Lallemandf9873ba2015-05-05 17:37:14 +02006535 if (dquote) {
6536 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
6537 err_code |= ERR_ALERT | ERR_FATAL;
6538 }
6539
6540 if (squote) {
6541 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
6542 err_code |= ERR_ALERT | ERR_FATAL;
6543 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006544
6545 /* empty line */
6546 if (!**args)
6547 continue;
6548
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006549 if (*line) {
6550 /* we had to stop due to too many args.
6551 * Let's terminate the string, print the offending part then cut the
6552 * last arg.
6553 */
6554 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6555 line++;
6556 *line = '\0';
6557
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006558 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006559 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006560 err_code |= ERR_ALERT | ERR_FATAL;
6561 args[arg] = line;
6562 }
6563
Willy Tarreau540abe42007-05-02 20:50:16 +02006564 /* zero out remaining args and ensure that at least one entry
6565 * is zeroed out.
6566 */
6567 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006568 args[arg] = line;
6569 }
6570
Willy Tarreau3842f002009-06-14 11:39:52 +02006571 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006572 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006573 char *tmp;
6574
Willy Tarreau3842f002009-06-14 11:39:52 +02006575 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006576 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006577 for (arg=0; *args[arg+1]; arg++)
6578 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006579 *tmp = '\0'; // fix the next arg to \0
6580 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006581 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006582 else if (!strcmp(args[0], "default")) {
6583 kwm = KWM_DEF;
6584 for (arg=0; *args[arg+1]; arg++)
6585 args[arg] = args[arg+1]; // shift args after inversion
6586 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006587
William Lallemand0f99e342011-10-12 17:50:54 +02006588 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6589 strcmp(args[0], "log") != 0) {
6590 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006591 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006592 }
6593
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006594 /* detect section start */
6595 list_for_each_entry(ics, &sections, list) {
6596 if (strcmp(args[0], ics->section_name) == 0) {
6597 cursection = ics->section_name;
6598 cs = ics;
6599 break;
6600 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006601 }
6602
Willy Tarreaubaaee002006-06-26 02:48:02 +02006603 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006604 if (cs)
6605 err_code |= cs->section_parser(file, linenum, args, kwm);
6606 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006607 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006608 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006609 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006610
6611 if (err_code & ERR_ABORT)
6612 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006613 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006614 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02006615 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006616 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006617 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006618}
6619
Willy Tarreau64ab6072014-09-16 12:17:36 +02006620/* This function propagates processes from frontend <from> to backend <to> so
6621 * that it is always guaranteed that a backend pointed to by a frontend is
6622 * bound to all of its processes. After that, if the target is a "listen"
6623 * instance, the function recursively descends the target's own targets along
6624 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6625 * checked first to ensure that <to> is already bound to all processes of
6626 * <from>, there is no risk of looping and we ensure to follow the shortest
6627 * path to the destination.
6628 *
6629 * It is possible to set <to> to NULL for the first call so that the function
6630 * takes care of visiting the initial frontend in <from>.
6631 *
6632 * It is important to note that the function relies on the fact that all names
6633 * have already been resolved.
6634 */
6635void propagate_processes(struct proxy *from, struct proxy *to)
6636{
6637 struct switching_rule *rule;
6638 struct hdr_exp *exp;
6639
6640 if (to) {
6641 /* check whether we need to go down */
6642 if (from->bind_proc &&
6643 (from->bind_proc & to->bind_proc) == from->bind_proc)
6644 return;
6645
6646 if (!from->bind_proc && !to->bind_proc)
6647 return;
6648
6649 to->bind_proc = from->bind_proc ?
6650 (to->bind_proc | from->bind_proc) : 0;
6651
6652 /* now propagate down */
6653 from = to;
6654 }
6655
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006656 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006657 return;
6658
Willy Tarreauf6b70012014-12-18 14:00:43 +01006659 if (from->state == PR_STSTOPPED)
6660 return;
6661
Willy Tarreau64ab6072014-09-16 12:17:36 +02006662 /* default_backend */
6663 if (from->defbe.be)
6664 propagate_processes(from, from->defbe.be);
6665
6666 /* use_backend */
6667 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006668 if (rule->dynamic)
6669 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006670 to = rule->be.backend;
6671 propagate_processes(from, to);
6672 }
6673
6674 /* reqsetbe */
6675 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6676 if (exp->action != ACT_SETBE)
6677 continue;
6678 to = (struct proxy *)exp->replace;
6679 propagate_processes(from, to);
6680 }
6681}
6682
Willy Tarreaubb925012009-07-23 13:36:36 +02006683/*
6684 * Returns the error code, 0 if OK, or any combination of :
6685 * - ERR_ABORT: must abort ASAP
6686 * - ERR_FATAL: we can continue parsing but not start the service
6687 * - ERR_WARN: a warning has been emitted
6688 * - ERR_ALERT: an alert has been emitted
6689 * Only the two first ones can stop processing, the two others are just
6690 * indicators.
6691 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006692int check_config_validity()
6693{
6694 int cfgerr = 0;
6695 struct proxy *curproxy = NULL;
6696 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006697 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006698 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006699 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006700
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006701 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006702 /*
6703 * Now, check for the integrity of all that we have collected.
6704 */
6705
6706 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006707 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006708
Willy Tarreau193b8c62012-11-22 00:17:38 +01006709 if (!global.tune.max_http_hdr)
6710 global.tune.max_http_hdr = MAX_HTTP_HDR;
6711
6712 if (!global.tune.cookie_len)
6713 global.tune.cookie_len = CAPTURE_LEN;
6714
6715 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6716
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006717 /* Post initialisation of the users and groups lists. */
6718 err_code = userlist_postinit();
6719 if (err_code != ERR_NONE)
6720 goto out;
6721
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006722 /* first, we will invert the proxy list order */
6723 curproxy = NULL;
6724 while (proxy) {
6725 struct proxy *next;
6726
6727 next = proxy->next;
6728 proxy->next = curproxy;
6729 curproxy = proxy;
6730 if (!next)
6731 break;
6732 proxy = next;
6733 }
6734
Willy Tarreau419ead82014-09-16 13:41:21 +02006735 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006736 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006737 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006738 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006739 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006740 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006741 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006742 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006743
Willy Tarreau050536d2012-10-04 08:47:34 +02006744 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006745 /* proxy ID not set, use automatic numbering with first
6746 * spare entry starting with next_pxid.
6747 */
6748 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6749 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6750 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006751 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006752 next_pxid++;
6753
Willy Tarreau55ea7572007-06-17 19:56:27 +02006754
Willy Tarreaubaaee002006-06-26 02:48:02 +02006755 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006756 /* ensure we don't keep listeners uselessly bound */
6757 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02006758 free((void *)curproxy->table.peers.name);
6759 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006760 continue;
6761 }
6762
Willy Tarreau102df612014-05-07 23:56:38 +02006763 /* Check multi-process mode compatibility for the current proxy */
6764
6765 if (curproxy->bind_proc) {
6766 /* an explicit bind-process was specified, let's check how many
6767 * processes remain.
6768 */
6769 nbproc = popcount(curproxy->bind_proc);
6770
6771 curproxy->bind_proc &= nbits(global.nbproc);
6772 if (!curproxy->bind_proc && nbproc == 1) {
6773 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);
6774 curproxy->bind_proc = 1;
6775 }
6776 else if (!curproxy->bind_proc && nbproc > 1) {
6777 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);
6778 curproxy->bind_proc = 0;
6779 }
6780 }
6781
Willy Tarreau3d209582014-05-09 17:06:11 +02006782 /* check and reduce the bind-proc of each listener */
6783 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6784 unsigned long mask;
6785
6786 if (!bind_conf->bind_proc)
6787 continue;
6788
6789 mask = nbits(global.nbproc);
6790 if (curproxy->bind_proc)
6791 mask &= curproxy->bind_proc;
6792 /* mask cannot be null here thanks to the previous checks */
6793
6794 nbproc = popcount(bind_conf->bind_proc);
6795 bind_conf->bind_proc &= mask;
6796
6797 if (!bind_conf->bind_proc && nbproc == 1) {
6798 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",
6799 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6800 bind_conf->bind_proc = mask & ~(mask - 1);
6801 }
6802 else if (!bind_conf->bind_proc && nbproc > 1) {
6803 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",
6804 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6805 bind_conf->bind_proc = 0;
6806 }
6807 }
6808
Willy Tarreauff01a212009-03-15 13:46:16 +01006809 switch (curproxy->mode) {
6810 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006811 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006812 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006813 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6814 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006815 cfgerr++;
6816 }
6817
6818 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006819 Warning("config : servers will be ignored for %s '%s'.\n",
6820 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006821 break;
6822
6823 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006824 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006825 break;
6826
6827 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006828 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006829 break;
6830 }
6831
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006832 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006833 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006834 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006835 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6836 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006837 cfgerr++;
6838 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006839#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006840 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006841 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6842 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006843 cfgerr++;
6844 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006845#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006846 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006847 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6848 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006849 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006850 }
6851 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006852 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006853 /* If no LB algo is set in a backend, and we're not in
6854 * transparent mode, dispatch mode nor proxy mode, we
6855 * want to use balance roundrobin by default.
6856 */
6857 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6858 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006859 }
6860 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006861
Willy Tarreau1620ec32011-08-06 17:05:02 +02006862 if (curproxy->options & PR_O_DISPATCH)
6863 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6864 else if (curproxy->options & PR_O_HTTP_PROXY)
6865 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6866 else if (curproxy->options & PR_O_TRANSP)
6867 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006868
Willy Tarreau1620ec32011-08-06 17:05:02 +02006869 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6870 if (curproxy->options & PR_O_DISABLE404) {
6871 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6872 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6873 err_code |= ERR_WARN;
6874 curproxy->options &= ~PR_O_DISABLE404;
6875 }
6876 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6877 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6878 "send-state", proxy_type_str(curproxy), curproxy->id);
6879 err_code |= ERR_WARN;
6880 curproxy->options &= ~PR_O2_CHK_SNDST;
6881 }
Willy Tarreauef781042010-01-27 11:53:01 +01006882 }
6883
Simon Horman98637e52014-06-20 12:30:16 +09006884 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6885 if (!global.external_check) {
6886 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6887 curproxy->id, "option external-check");
6888 cfgerr++;
6889 }
6890 if (!curproxy->check_command) {
6891 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6892 curproxy->id, "option external-check");
6893 cfgerr++;
6894 }
6895 }
6896
Simon Horman64e34162015-02-06 11:11:57 +09006897 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006898 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
6899 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09006900 "'email-alert from', 'email-alert level' 'email-alert mailer', "
6901 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006902 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
6903 "to be present).\n",
6904 proxy_type_str(curproxy), curproxy->id);
6905 err_code |= ERR_WARN;
6906 free_email_alert(curproxy);
6907 }
6908 if (!curproxy->email_alert.myhostname)
6909 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09006910 }
6911
Simon Horman98637e52014-06-20 12:30:16 +09006912 if (curproxy->check_command) {
6913 int clear = 0;
6914 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6915 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6916 "external-check command", proxy_type_str(curproxy), curproxy->id);
6917 err_code |= ERR_WARN;
6918 clear = 1;
6919 }
6920 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6921 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6922 curproxy->id, "external-check command");
6923 cfgerr++;
6924 }
6925 if (clear) {
6926 free(curproxy->check_command);
6927 curproxy->check_command = NULL;
6928 }
6929 }
6930
6931 if (curproxy->check_path) {
6932 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6933 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6934 "external-check path", proxy_type_str(curproxy), curproxy->id);
6935 err_code |= ERR_WARN;
6936 free(curproxy->check_path);
6937 curproxy->check_path = NULL;
6938 }
6939 }
6940
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006941 /* if a default backend was specified, let's find it */
6942 if (curproxy->defbe.name) {
6943 struct proxy *target;
6944
Alex Williams96532db2009-11-01 21:27:13 -05006945 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006946 if (!target) {
6947 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6948 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006949 cfgerr++;
6950 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006951 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6952 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006953 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006954 } else {
6955 free(curproxy->defbe.name);
6956 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006957
6958 /* Emit a warning if this proxy also has some servers */
6959 if (curproxy->srv) {
6960 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6961 curproxy->id);
6962 err_code |= ERR_WARN;
6963 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006964 }
6965 }
6966
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006967 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006968 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6969 /* map jump target for ACT_SETBE in req_rep chain */
6970 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006971 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006972 struct proxy *target;
6973
Willy Tarreaua496b602006-12-17 23:15:24 +01006974 if (exp->action != ACT_SETBE)
6975 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006976
Alex Williams96532db2009-11-01 21:27:13 -05006977 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006978 if (!target) {
6979 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6980 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006981 cfgerr++;
6982 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006983 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6984 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006985 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006986 } else {
6987 free((void *)exp->replace);
6988 exp->replace = (const char *)target;
6989 }
6990 }
6991 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006992
6993 /* find the target proxy for 'use_backend' rules */
6994 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006995 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006996 struct logformat_node *node;
6997 char *pxname;
6998
6999 /* Try to parse the string as a log format expression. If the result
7000 * of the parsing is only one entry containing a simple string, then
7001 * it's a standard string corresponding to a static rule, thus the
7002 * parsing is cancelled and be.name is restored to be resolved.
7003 */
7004 pxname = rule->be.name;
7005 LIST_INIT(&rule->be.expr);
7006 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7007 curproxy->conf.args.file, curproxy->conf.args.line);
7008 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7009
7010 if (!LIST_ISEMPTY(&rule->be.expr)) {
7011 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7012 rule->dynamic = 1;
7013 free(pxname);
7014 continue;
7015 }
7016 /* simple string: free the expression and fall back to static rule */
7017 free(node->arg);
7018 free(node);
7019 }
7020
7021 rule->dynamic = 0;
7022 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007023
Alex Williams96532db2009-11-01 21:27:13 -05007024 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007025
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007026 if (!target) {
7027 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7028 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007029 cfgerr++;
7030 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007031 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7032 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007033 cfgerr++;
7034 } else {
7035 free((void *)rule->be.name);
7036 rule->be.backend = target;
7037 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007038 }
7039
Willy Tarreau64ab6072014-09-16 12:17:36 +02007040 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007041 list_for_each_entry(srule, &curproxy->server_rules, list) {
7042 struct server *target = findserver(curproxy, srule->srv.name);
7043
7044 if (!target) {
7045 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7046 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7047 cfgerr++;
7048 continue;
7049 }
7050 free((void *)srule->srv.name);
7051 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007052 }
7053
Emeric Brunb982a3d2010-01-04 15:45:53 +01007054 /* find the target table for 'stick' rules */
7055 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7056 struct proxy *target;
7057
Emeric Brun1d33b292010-01-04 15:47:17 +01007058 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7059 if (mrule->flags & STK_IS_STORE)
7060 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7061
Emeric Brunb982a3d2010-01-04 15:45:53 +01007062 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007063 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007064 else
7065 target = curproxy;
7066
7067 if (!target) {
7068 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7069 curproxy->id, mrule->table.name);
7070 cfgerr++;
7071 }
7072 else if (target->table.size == 0) {
7073 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7074 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7075 cfgerr++;
7076 }
Willy Tarreau12785782012-04-27 21:37:17 +02007077 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7078 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007079 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7080 cfgerr++;
7081 }
7082 else {
7083 free((void *)mrule->table.name);
7084 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007085 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007086 }
7087 }
7088
7089 /* find the target table for 'store response' rules */
7090 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7091 struct proxy *target;
7092
Emeric Brun1d33b292010-01-04 15:47:17 +01007093 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7094
Emeric Brunb982a3d2010-01-04 15:45:53 +01007095 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007096 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007097 else
7098 target = curproxy;
7099
7100 if (!target) {
7101 Alert("Proxy '%s': unable to find store table '%s'.\n",
7102 curproxy->id, mrule->table.name);
7103 cfgerr++;
7104 }
7105 else if (target->table.size == 0) {
7106 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7107 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7108 cfgerr++;
7109 }
Willy Tarreau12785782012-04-27 21:37:17 +02007110 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7111 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007112 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7113 cfgerr++;
7114 }
7115 else {
7116 free((void *)mrule->table.name);
7117 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007118 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007119 }
7120 }
7121
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007122 /* find the target table for 'tcp-request' layer 4 rules */
7123 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7124 struct proxy *target;
7125
Willy Tarreaub4c84932013-07-23 19:15:30 +02007126 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007127 continue;
7128
7129 if (trule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007130 target = proxy_tbl_by_name(trule->act_prm.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007131 else
7132 target = curproxy;
7133
7134 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007135 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7136 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007137 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007138 cfgerr++;
7139 }
7140 else if (target->table.size == 0) {
7141 Alert("Proxy '%s': table '%s' used but not configured.\n",
7142 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7143 cfgerr++;
7144 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007145 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7146 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7147 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 +01007148 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007149 cfgerr++;
7150 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007151 else {
7152 free(trule->act_prm.trk_ctr.table.n);
7153 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007154 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007155 * to pass a list of counters to track and allocate them right here using
7156 * stktable_alloc_data_type().
7157 */
7158 }
7159 }
7160
Willy Tarreaud1f96522010-08-03 19:34:32 +02007161 /* find the target table for 'tcp-request' layer 6 rules */
7162 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7163 struct proxy *target;
7164
Willy Tarreaub4c84932013-07-23 19:15:30 +02007165 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007166 continue;
7167
7168 if (trule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007169 target = proxy_tbl_by_name(trule->act_prm.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007170 else
7171 target = curproxy;
7172
7173 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007174 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7175 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007176 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007177 cfgerr++;
7178 }
7179 else if (target->table.size == 0) {
7180 Alert("Proxy '%s': table '%s' used but not configured.\n",
7181 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7182 cfgerr++;
7183 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007184 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7185 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7186 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 +01007187 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007188 cfgerr++;
7189 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007190 else {
7191 free(trule->act_prm.trk_ctr.table.n);
7192 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007193 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007194 * to pass a list of counters to track and allocate them right here using
7195 * stktable_alloc_data_type().
7196 */
7197 }
7198 }
7199
Willy Tarreau09448f72014-06-25 18:12:15 +02007200 /* find the target table for 'http-request' layer 7 rules */
7201 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7202 struct proxy *target;
7203
7204 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
7205 continue;
7206
7207 if (hrqrule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007208 target = proxy_tbl_by_name(hrqrule->act_prm.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007209 else
7210 target = curproxy;
7211
7212 if (!target) {
7213 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7214 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
7215 http_req_trk_idx(hrqrule->action));
7216 cfgerr++;
7217 }
7218 else if (target->table.size == 0) {
7219 Alert("Proxy '%s': table '%s' used but not configured.\n",
7220 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
7221 cfgerr++;
7222 }
7223 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
7224 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7225 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
7226 http_req_trk_idx(hrqrule->action));
7227 cfgerr++;
7228 }
7229 else {
7230 free(hrqrule->act_prm.trk_ctr.table.n);
7231 hrqrule->act_prm.trk_ctr.table.t = &target->table;
7232 /* Note: if we decide to enhance the track-sc syntax, we may be able
7233 * to pass a list of counters to track and allocate them right here using
7234 * stktable_alloc_data_type().
7235 */
7236 }
7237 }
7238
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007239 /* move any "block" rules at the beginning of the http-request rules */
7240 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7241 /* insert block_rules into http_req_rules at the beginning */
7242 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7243 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7244 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7245 curproxy->http_req_rules.n = curproxy->block_rules.n;
7246 LIST_INIT(&curproxy->block_rules);
7247 }
7248
Emeric Brun32da3c42010-09-23 18:39:19 +02007249 if (curproxy->table.peers.name) {
7250 struct peers *curpeers = peers;
7251
7252 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7253 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7254 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007255 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007256 break;
7257 }
7258 }
7259
7260 if (!curpeers) {
7261 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7262 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007263 free((void *)curproxy->table.peers.name);
7264 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007265 cfgerr++;
7266 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007267 else if (curpeers->state == PR_STSTOPPED) {
7268 /* silently disable this peers section */
7269 curproxy->table.peers.p = NULL;
7270 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007271 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007272 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7273 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007274 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007275 cfgerr++;
7276 }
7277 }
7278
Simon Horman9dc49962015-01-30 11:22:59 +09007279
7280 if (curproxy->email_alert.mailers.name) {
7281 struct mailers *curmailers = mailers;
7282
7283 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7284 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7285 free(curproxy->email_alert.mailers.name);
7286 curproxy->email_alert.mailers.m = curmailers;
7287 curmailers->users++;
7288 break;
7289 }
7290 }
7291
7292 if (!curmailers) {
7293 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7294 curproxy->id, curproxy->email_alert.mailers.name);
7295 free_email_alert(curproxy);
7296 cfgerr++;
7297 }
7298 }
7299
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007300 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007301 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007302 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7303 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7304 "proxy", curproxy->id);
7305 cfgerr++;
7306 goto out_uri_auth_compat;
7307 }
7308
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007309 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007310 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007311 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007312 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007313
Willy Tarreau95fa4692010-02-01 13:05:50 +01007314 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7315 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007316
7317 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007318 uri_auth_compat_req[i++] = "realm";
7319 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7320 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007321
Willy Tarreau95fa4692010-02-01 13:05:50 +01007322 uri_auth_compat_req[i++] = "unless";
7323 uri_auth_compat_req[i++] = "{";
7324 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7325 uri_auth_compat_req[i++] = "}";
7326 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007327
Willy Tarreauff011f22011-01-06 17:51:27 +01007328 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7329 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007330 cfgerr++;
7331 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007332 }
7333
Willy Tarreauff011f22011-01-06 17:51:27 +01007334 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007335
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007336 if (curproxy->uri_auth->auth_realm) {
7337 free(curproxy->uri_auth->auth_realm);
7338 curproxy->uri_auth->auth_realm = NULL;
7339 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007340
7341 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007342 }
7343out_uri_auth_compat:
7344
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007345 /* compile the log format */
7346 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007347 if (curproxy->conf.logformat_string != default_http_log_format &&
7348 curproxy->conf.logformat_string != default_tcp_log_format &&
7349 curproxy->conf.logformat_string != clf_http_log_format)
7350 free(curproxy->conf.logformat_string);
7351 curproxy->conf.logformat_string = NULL;
7352 free(curproxy->conf.lfs_file);
7353 curproxy->conf.lfs_file = NULL;
7354 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007355 }
7356
Willy Tarreau62a61232013-04-12 18:13:46 +02007357 if (curproxy->conf.logformat_string) {
7358 curproxy->conf.args.ctx = ARGC_LOG;
7359 curproxy->conf.args.file = curproxy->conf.lfs_file;
7360 curproxy->conf.args.line = curproxy->conf.lfs_line;
7361 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007362 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007363 curproxy->conf.args.file = NULL;
7364 curproxy->conf.args.line = 0;
7365 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007366
Willy Tarreau62a61232013-04-12 18:13:46 +02007367 if (curproxy->conf.uniqueid_format_string) {
7368 curproxy->conf.args.ctx = ARGC_UIF;
7369 curproxy->conf.args.file = curproxy->conf.uif_file;
7370 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007371 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007372 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007373 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007374 curproxy->conf.args.file = NULL;
7375 curproxy->conf.args.line = 0;
7376 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007377
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007378 /* only now we can check if some args remain unresolved.
7379 * This must be done after the users and groups resolution.
7380 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007381 cfgerr += smp_resolve_args(curproxy);
7382 if (!cfgerr)
7383 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007384
Willy Tarreau2738a142006-07-08 17:28:09 +02007385 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007386 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007387 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007388 (!curproxy->timeout.connect ||
7389 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007390 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007391 " | While not properly invalid, you will certainly encounter various problems\n"
7392 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007393 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007394 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007395 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007396 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007397
Willy Tarreau1fa31262007-12-03 00:36:16 +01007398 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7399 * We must still support older configurations, so let's find out whether those
7400 * parameters have been set or must be copied from contimeouts.
7401 */
7402 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007403 if (!curproxy->timeout.tarpit ||
7404 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007405 /* tarpit timeout not set. We search in the following order:
7406 * default.tarpit, curr.connect, default.connect.
7407 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007408 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007409 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007410 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007411 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007412 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007413 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007414 }
7415 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007416 (!curproxy->timeout.queue ||
7417 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007418 /* queue timeout not set. We search in the following order:
7419 * default.queue, curr.connect, default.connect.
7420 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007421 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007422 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007423 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007424 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007425 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007426 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007427 }
7428 }
7429
Willy Tarreau1620ec32011-08-06 17:05:02 +02007430 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007431 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7432 curproxy->check_req = (char *)malloc(curproxy->check_len);
7433 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007434 }
7435
Willy Tarreau215663d2014-06-13 18:30:23 +02007436 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7437 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7438 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7439 proxy_type_str(curproxy), curproxy->id);
7440 err_code |= ERR_WARN;
7441 }
7442
Willy Tarreau193b8c62012-11-22 00:17:38 +01007443 /* ensure that cookie capture length is not too large */
7444 if (curproxy->capture_len >= global.tune.cookie_len) {
7445 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7446 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7447 err_code |= ERR_WARN;
7448 curproxy->capture_len = global.tune.cookie_len - 1;
7449 }
7450
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007451 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007452 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007453 curproxy->req_cap_pool = create_pool("ptrcap",
7454 curproxy->nb_req_cap * sizeof(char *),
7455 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007456 }
7457
7458 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007459 curproxy->rsp_cap_pool = create_pool("ptrcap",
7460 curproxy->nb_rsp_cap * sizeof(char *),
7461 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007462 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007463
Willy Tarreaubaaee002006-06-26 02:48:02 +02007464 /* first, we will invert the servers list order */
7465 newsrv = NULL;
7466 while (curproxy->srv) {
7467 struct server *next;
7468
7469 next = curproxy->srv->next;
7470 curproxy->srv->next = newsrv;
7471 newsrv = curproxy->srv;
7472 if (!next)
7473 break;
7474 curproxy->srv = next;
7475 }
7476
Willy Tarreau17edc812014-01-03 12:14:34 +01007477 /* Check that no server name conflicts. This causes trouble in the stats.
7478 * We only emit a warning for the first conflict affecting each server,
7479 * in order to avoid combinatory explosion if all servers have the same
7480 * name. We do that only for servers which do not have an explicit ID,
7481 * because these IDs were made also for distinguishing them and we don't
7482 * want to annoy people who correctly manage them.
7483 */
7484 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7485 struct server *other_srv;
7486
7487 if (newsrv->puid)
7488 continue;
7489
7490 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7491 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7492 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7493 newsrv->conf.file, newsrv->conf.line,
7494 proxy_type_str(curproxy), curproxy->id,
7495 newsrv->id, other_srv->conf.line);
7496 break;
7497 }
7498 }
7499 }
7500
Willy Tarreaudd701652010-05-25 23:03:02 +02007501 /* assign automatic UIDs to servers which don't have one yet */
7502 next_id = 1;
7503 newsrv = curproxy->srv;
7504 while (newsrv != NULL) {
7505 if (!newsrv->puid) {
7506 /* server ID not set, use automatic numbering with first
7507 * spare entry starting with next_svid.
7508 */
7509 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7510 newsrv->conf.id.key = newsrv->puid = next_id;
7511 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7512 }
7513 next_id++;
7514 newsrv = newsrv->next;
7515 }
7516
Willy Tarreau20697042007-11-15 23:26:18 +01007517 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007518 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007519
Willy Tarreau62c3be22012-01-20 13:12:32 +01007520 /*
7521 * If this server supports a maxconn parameter, it needs a dedicated
7522 * tasks to fill the emptied slots when a connection leaves.
7523 * Also, resolve deferred tracking dependency if needed.
7524 */
7525 newsrv = curproxy->srv;
7526 while (newsrv != NULL) {
7527 if (newsrv->minconn > newsrv->maxconn) {
7528 /* Only 'minconn' was specified, or it was higher than or equal
7529 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7530 * this will avoid further useless expensive computations.
7531 */
7532 newsrv->maxconn = newsrv->minconn;
7533 } else if (newsrv->maxconn && !newsrv->minconn) {
7534 /* minconn was not specified, so we set it to maxconn */
7535 newsrv->minconn = newsrv->maxconn;
7536 }
7537
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007538#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007539 if (newsrv->use_ssl || newsrv->check.use_ssl)
7540 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007541#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007542
Willy Tarreau2f075e92013-12-03 11:11:34 +01007543 /* set the check type on the server */
7544 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7545
Willy Tarreau62c3be22012-01-20 13:12:32 +01007546 if (newsrv->trackit) {
7547 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007548 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007549 char *pname, *sname;
7550
7551 pname = newsrv->trackit;
7552 sname = strrchr(pname, '/');
7553
7554 if (sname)
7555 *sname++ = '\0';
7556 else {
7557 sname = pname;
7558 pname = NULL;
7559 }
7560
7561 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007562 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007563 if (!px) {
7564 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7565 proxy_type_str(curproxy), curproxy->id,
7566 newsrv->id, pname);
7567 cfgerr++;
7568 goto next_srv;
7569 }
7570 } else
7571 px = curproxy;
7572
7573 srv = findserver(px, sname);
7574 if (!srv) {
7575 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7576 proxy_type_str(curproxy), curproxy->id,
7577 newsrv->id, sname);
7578 cfgerr++;
7579 goto next_srv;
7580 }
7581
Willy Tarreau32091232014-05-16 13:52:00 +02007582 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7583 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7584 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007585 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007586 "tracking as it does not have any check nor agent enabled.\n",
7587 proxy_type_str(curproxy), curproxy->id,
7588 newsrv->id, px->id, srv->id);
7589 cfgerr++;
7590 goto next_srv;
7591 }
7592
7593 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7594
7595 if (loop) {
7596 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7597 "belongs to a tracking chain looping back to %s/%s.\n",
7598 proxy_type_str(curproxy), curproxy->id,
7599 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007600 cfgerr++;
7601 goto next_srv;
7602 }
7603
7604 if (curproxy != px &&
7605 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7606 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7607 "tracking: disable-on-404 option inconsistency.\n",
7608 proxy_type_str(curproxy), curproxy->id,
7609 newsrv->id, px->id, srv->id);
7610 cfgerr++;
7611 goto next_srv;
7612 }
7613
7614 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007615 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007616 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007617 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007618 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007619 }
7620
7621 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007622 newsrv->tracknext = srv->trackers;
7623 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007624
7625 free(newsrv->trackit);
7626 newsrv->trackit = NULL;
7627 }
7628 next_srv:
7629 newsrv = newsrv->next;
7630 }
7631
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007632 /* We have to initialize the server lookup mechanism depending
7633 * on what LB algorithm was choosen.
7634 */
7635
7636 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7637 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7638 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007639 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7640 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7641 init_server_map(curproxy);
7642 } else {
7643 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7644 fwrr_init_server_groups(curproxy);
7645 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007646 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007647
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007648 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007649 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7650 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7651 fwlc_init_server_tree(curproxy);
7652 } else {
7653 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7654 fas_init_server_tree(curproxy);
7655 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007656 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007657
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007658 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007659 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7660 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7661 chash_init_server_tree(curproxy);
7662 } else {
7663 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7664 init_server_map(curproxy);
7665 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007666 break;
7667 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007668
7669 if (curproxy->options & PR_O_LOGASAP)
7670 curproxy->to_log &= ~LW_BYTES;
7671
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007672 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007673 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007674 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7675 proxy_type_str(curproxy), curproxy->id);
7676 err_code |= ERR_WARN;
7677 }
7678
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007679 if (curproxy->mode != PR_MODE_HTTP) {
7680 int optnum;
7681
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007682 if (curproxy->uri_auth) {
7683 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7684 proxy_type_str(curproxy), curproxy->id);
7685 err_code |= ERR_WARN;
7686 curproxy->uri_auth = NULL;
7687 }
7688
Willy Tarreau87cf5142011-08-19 22:57:24 +02007689 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007690 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7691 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7692 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007693 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007694 }
7695
7696 if (curproxy->options & PR_O_ORGTO) {
7697 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7698 "originalto", proxy_type_str(curproxy), curproxy->id);
7699 err_code |= ERR_WARN;
7700 curproxy->options &= ~PR_O_ORGTO;
7701 }
7702
7703 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7704 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7705 (curproxy->cap & cfg_opts[optnum].cap) &&
7706 (curproxy->options & cfg_opts[optnum].val)) {
7707 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7708 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7709 err_code |= ERR_WARN;
7710 curproxy->options &= ~cfg_opts[optnum].val;
7711 }
7712 }
7713
7714 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7715 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7716 (curproxy->cap & cfg_opts2[optnum].cap) &&
7717 (curproxy->options2 & cfg_opts2[optnum].val)) {
7718 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7719 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7720 err_code |= ERR_WARN;
7721 curproxy->options2 &= ~cfg_opts2[optnum].val;
7722 }
7723 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007724
Pieter Baauwd551fb52013-05-08 22:49:23 +02007725#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007726 if (curproxy->conn_src.bind_hdr_occ) {
7727 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007728 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007729 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007730 err_code |= ERR_WARN;
7731 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007732#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007733 }
7734
Willy Tarreaubaaee002006-06-26 02:48:02 +02007735 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007736 * ensure that we're not cross-dressing a TCP server into HTTP.
7737 */
7738 newsrv = curproxy->srv;
7739 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007740 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007741 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7742 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007743 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007744 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007745
Willy Tarreau0cec3312011-10-31 13:49:26 +01007746 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7747 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7748 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7749 err_code |= ERR_WARN;
7750 }
7751
Willy Tarreauc93cd162014-05-13 15:54:22 +02007752 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007753 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7754 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7755 err_code |= ERR_WARN;
7756 }
7757
Pieter Baauwd551fb52013-05-08 22:49:23 +02007758#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007759 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7760 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007761 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 +01007762 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007763 err_code |= ERR_WARN;
7764 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007765#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007766 newsrv = newsrv->next;
7767 }
7768
Willy Tarreaue42bd962014-09-16 16:21:19 +02007769 /* check if we have a frontend with "tcp-request content" looking at L7
7770 * with no inspect-delay
7771 */
7772 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7773 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7774 if (trule->action == TCP_ACT_CAPTURE &&
7775 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7776 break;
7777 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7778 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7779 break;
7780 }
7781
7782 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7783 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7784 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7785 " This means that these rules will randomly find their contents. This can be fixed by"
7786 " setting the tcp-request inspect-delay.\n",
7787 proxy_type_str(curproxy), curproxy->id);
7788 err_code |= ERR_WARN;
7789 }
7790 }
7791
Willy Tarreauc1a21672009-08-16 22:37:44 +02007792 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007793 if (!curproxy->accept)
7794 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007795
Willy Tarreauc1a21672009-08-16 22:37:44 +02007796 if (curproxy->tcp_req.inspect_delay ||
7797 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007798 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007799
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007800 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007801 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007802 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007803 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007804
7805 /* both TCP and HTTP must check switching rules */
7806 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7807 }
7808
7809 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007810 if (curproxy->tcp_req.inspect_delay ||
7811 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7812 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7813
Emeric Brun97679e72010-09-23 17:56:44 +02007814 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7815 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7816
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007817 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007818 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007819 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007820 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007821
7822 /* If the backend does requires RDP cookie persistence, we have to
7823 * enable the corresponding analyser.
7824 */
7825 if (curproxy->options2 & PR_O2_RDPC_PRST)
7826 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7827 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007828 }
7829
7830 /***********************************************************/
7831 /* At this point, target names have already been resolved. */
7832 /***********************************************************/
7833
7834 /* Check multi-process mode compatibility */
7835
7836 if (global.nbproc > 1 && global.stats_fe) {
7837 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7838 unsigned long mask;
7839
7840 mask = nbits(global.nbproc);
7841 if (global.stats_fe->bind_proc)
7842 mask &= global.stats_fe->bind_proc;
7843
7844 if (bind_conf->bind_proc)
7845 mask &= bind_conf->bind_proc;
7846
7847 /* stop here if more than one process is used */
7848 if (popcount(mask) > 1)
7849 break;
7850 }
7851 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7852 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");
7853 }
7854 }
7855
7856 /* Make each frontend inherit bind-process from its listeners when not specified. */
7857 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7858 if (curproxy->bind_proc)
7859 continue;
7860
7861 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7862 unsigned long mask;
7863
Willy Tarreaue428b082015-05-04 21:57:58 +02007864 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007865 curproxy->bind_proc |= mask;
7866 }
7867
7868 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02007869 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007870 }
7871
7872 if (global.stats_fe) {
7873 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7874 unsigned long mask;
7875
Willy Tarreaue428b082015-05-04 21:57:58 +02007876 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007877 global.stats_fe->bind_proc |= mask;
7878 }
7879 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02007880 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007881 }
7882
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007883 /* propagate bindings from frontends to backends. Don't do it if there
7884 * are any fatal errors as we must not call it with unresolved proxies.
7885 */
7886 if (!cfgerr) {
7887 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7888 if (curproxy->cap & PR_CAP_FE)
7889 propagate_processes(curproxy, NULL);
7890 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007891 }
7892
7893 /* Bind each unbound backend to all processes when not specified. */
7894 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7895 if (curproxy->bind_proc)
7896 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02007897 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007898 }
7899
7900 /*******************************************************/
7901 /* At this step, all proxies have a non-null bind_proc */
7902 /*******************************************************/
7903
7904 /* perform the final checks before creating tasks */
7905
7906 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7907 struct listener *listener;
7908 unsigned int next_id;
7909 int nbproc;
7910
7911 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007912
Emeric Brunc52962f2012-11-15 18:28:02 +01007913#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007914 /* Configure SSL for each bind line.
7915 * Note: if configuration fails at some point, the ->ctx member
7916 * remains NULL so that listeners can later detach.
7917 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007918 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007919 int alloc_ctx;
7920
Emeric Brunc52962f2012-11-15 18:28:02 +01007921 if (!bind_conf->is_ssl) {
7922 if (bind_conf->default_ctx) {
7923 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7924 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7925 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007926 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007927 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007928 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007929 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007930 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007931 cfgerr++;
7932 continue;
7933 }
7934
Emeric Brun8dc60392014-05-09 13:52:00 +02007935 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007936 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007937 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7938 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");
7939 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007940 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007941 cfgerr++;
7942 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007943 }
7944
Emeric Brunfc0421f2012-09-07 17:30:07 +02007945 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007946 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007947 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007948#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007949
Willy Tarreaue6b98942007-10-29 01:09:36 +01007950 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007951 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007952 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007953 if (!listener->luid) {
7954 /* listener ID not set, use automatic numbering with first
7955 * spare entry starting with next_luid.
7956 */
7957 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7958 listener->conf.id.key = listener->luid = next_id;
7959 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007960 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007961 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007962
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007963 /* enable separate counters */
7964 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7965 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007966 if (!listener->name)
7967 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007968 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007969
Willy Tarreaue6b98942007-10-29 01:09:36 +01007970 if (curproxy->options & PR_O_TCP_NOLING)
7971 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007972 if (!listener->maxconn)
7973 listener->maxconn = curproxy->maxconn;
7974 if (!listener->backlog)
7975 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007976 if (!listener->maxaccept)
7977 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7978
7979 /* we want to have an optimal behaviour on single process mode to
7980 * maximize the work at once, but in multi-process we want to keep
7981 * some fairness between processes, so we target half of the max
7982 * number of events to be balanced over all the processes the proxy
7983 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7984 * used to disable the limit.
7985 */
7986 if (listener->maxaccept > 0) {
7987 if (nbproc > 1)
7988 listener->maxaccept = (listener->maxaccept + 1) / 2;
7989 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7990 }
7991
Willy Tarreau9903f0e2015-04-04 18:50:31 +02007992 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02007993 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007994 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01007995 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007996
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007997 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7998 listener->options |= LI_O_TCP_RULES;
7999
Willy Tarreaude3041d2010-05-31 10:56:17 +02008000 if (curproxy->mon_mask.s_addr)
8001 listener->options |= LI_O_CHK_MONNET;
8002
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008003 /* smart accept mode is automatic in HTTP mode */
8004 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008005 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008006 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8007 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008008 }
8009
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008010 /* Release unused SSL configs */
8011 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8012 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008013 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008014#ifdef USE_OPENSSL
8015 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008016 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008017 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008018 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008019 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008020 if(bind_conf->keys_ref) {
8021 free(bind_conf->keys_ref->filename);
8022 free(bind_conf->keys_ref->tlskeys);
8023 free(bind_conf->keys_ref);
8024 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008025#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008026 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008027
Willy Tarreau102df612014-05-07 23:56:38 +02008028 if (nbproc > 1) {
8029 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008030 int count, maxproc = 0;
8031
8032 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8033 count = popcount(bind_conf->bind_proc);
8034 if (count > maxproc)
8035 maxproc = count;
8036 }
8037 /* backends have 0, frontends have 1 or more */
8038 if (maxproc != 1)
8039 Warning("Proxy '%s': in multi-process mode, stats will be"
8040 " limited to process assigned to the current request.\n",
8041 curproxy->id);
8042
Willy Tarreau102df612014-05-07 23:56:38 +02008043 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8044 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8045 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008046 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008047 }
Willy Tarreau102df612014-05-07 23:56:38 +02008048 if (curproxy->appsession_name) {
8049 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
8050 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008051 }
Willy Tarreau102df612014-05-07 23:56:38 +02008052 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8053 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8054 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008055 }
8056 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008057
8058 /* create the task associated with the proxy */
8059 curproxy->task = task_new();
8060 if (curproxy->task) {
8061 curproxy->task->context = curproxy;
8062 curproxy->task->process = manage_proxy;
8063 /* no need to queue, it will be done automatically if some
8064 * listener gets limited.
8065 */
8066 curproxy->task->expire = TICK_ETERNITY;
8067 } else {
8068 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8069 curproxy->id);
8070 cfgerr++;
8071 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008072 }
8073
Willy Tarreaufbb78422011-06-05 15:38:35 +02008074 /* automatically compute fullconn if not set. We must not do it in the
8075 * loop above because cross-references are not yet fully resolved.
8076 */
8077 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8078 /* If <fullconn> is not set, let's set it to 10% of the sum of
8079 * the possible incoming frontend's maxconns.
8080 */
8081 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8082 struct proxy *fe;
8083 int total = 0;
8084
8085 /* sum up the number of maxconns of frontends which
8086 * reference this backend at least once or which are
8087 * the same one ('listen').
8088 */
8089 for (fe = proxy; fe; fe = fe->next) {
8090 struct switching_rule *rule;
8091 struct hdr_exp *exp;
8092 int found = 0;
8093
8094 if (!(fe->cap & PR_CAP_FE))
8095 continue;
8096
8097 if (fe == curproxy) /* we're on a "listen" instance */
8098 found = 1;
8099
8100 if (fe->defbe.be == curproxy) /* "default_backend" */
8101 found = 1;
8102
8103 /* check if a "use_backend" rule matches */
8104 if (!found) {
8105 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008106 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008107 found = 1;
8108 break;
8109 }
8110 }
8111 }
8112
8113 /* check if a "reqsetbe" rule matches */
8114 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
8115 if (exp->action == ACT_SETBE &&
8116 (struct proxy *)exp->replace == curproxy) {
8117 found = 1;
8118 break;
8119 }
8120 }
8121
8122 /* now we've checked all possible ways to reference a backend
8123 * from a frontend.
8124 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008125 if (!found)
8126 continue;
8127 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008128 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008129 /* we have the sum of the maxconns in <total>. We only
8130 * keep 10% of that sum to set the default fullconn, with
8131 * a hard minimum of 1 (to avoid a divide by zero).
8132 */
8133 curproxy->fullconn = (total + 9) / 10;
8134 if (!curproxy->fullconn)
8135 curproxy->fullconn = 1;
8136 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008137 }
8138
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008139 /*
8140 * Recount currently required checks.
8141 */
8142
8143 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8144 int optnum;
8145
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008146 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8147 if (curproxy->options & cfg_opts[optnum].val)
8148 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008149
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008150 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8151 if (curproxy->options2 & cfg_opts2[optnum].val)
8152 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008153 }
8154
Willy Tarreau0fca4832015-05-01 19:12:05 +02008155 /* compute the required process bindings for the peers */
8156 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8157 if (curproxy->table.peers.p)
8158 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8159
Willy Tarreau122541c2011-09-07 21:24:49 +02008160 if (peers) {
8161 struct peers *curpeers = peers, **last;
8162 struct peer *p, *pb;
8163
Willy Tarreau1e273012015-05-01 19:15:17 +02008164 /* Remove all peers sections which don't have a valid listener,
8165 * which are not used by any table, or which are bound to more
8166 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008167 */
8168 last = &peers;
8169 while (*last) {
8170 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008171
8172 if (curpeers->state == PR_STSTOPPED) {
8173 /* the "disabled" keyword was present */
8174 if (curpeers->peers_fe)
8175 stop_proxy(curpeers->peers_fe);
8176 curpeers->peers_fe = NULL;
8177 }
8178 else if (!curpeers->peers_fe) {
8179 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8180 curpeers->id, localpeer);
8181 }
Willy Tarreau1e273012015-05-01 19:15:17 +02008182 else if (popcount(curpeers->peers_fe->bind_proc) != 1) {
8183 /* either it's totally stopped or too much used */
8184 if (curpeers->peers_fe->bind_proc) {
8185 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008186 "running in different processes (%d different ones). "
8187 "Check global.nbproc and all tables' bind-process "
8188 "settings.\n", curpeers->id, popcount(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008189 cfgerr++;
8190 }
8191 stop_proxy(curpeers->peers_fe);
8192 curpeers->peers_fe = NULL;
8193 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008194 else {
Willy Tarreau122541c2011-09-07 21:24:49 +02008195 last = &curpeers->next;
8196 continue;
8197 }
8198
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008199 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008200 p = curpeers->remote;
8201 while (p) {
8202 pb = p->next;
8203 free(p->id);
8204 free(p);
8205 p = pb;
8206 }
8207
8208 /* Destroy and unlink this curpeers section.
8209 * Note: curpeers is backed up into *last.
8210 */
8211 free(curpeers->id);
8212 curpeers = curpeers->next;
8213 free(*last);
8214 *last = curpeers;
8215 }
8216 }
8217
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008218 /* initialize stick-tables on backend capable proxies. This must not
8219 * be done earlier because the data size may be discovered while parsing
8220 * other proxies.
8221 */
8222 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8223 if (curproxy->state == PR_STSTOPPED)
8224 continue;
8225
8226 if (!stktable_init(&curproxy->table)) {
8227 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8228 cfgerr++;
8229 }
8230 }
8231
Simon Horman0d16a402015-01-30 11:22:58 +09008232 if (mailers) {
8233 struct mailers *curmailers = mailers, **last;
8234 struct mailer *m, *mb;
8235
8236 /* Remove all mailers sections which don't have a valid listener.
8237 * This can happen when a mailers section is never referenced.
8238 */
8239 last = &mailers;
8240 while (*last) {
8241 curmailers = *last;
8242 if (curmailers->users) {
8243 last = &curmailers->next;
8244 continue;
8245 }
8246
8247 Warning("Removing incomplete section 'mailers %s'.\n",
8248 curmailers->id);
8249
8250 m = curmailers->mailer_list;
8251 while (m) {
8252 mb = m->next;
8253 free(m->id);
8254 free(m);
8255 m = mb;
8256 }
8257
8258 /* Destroy and unlink this curmailers section.
8259 * Note: curmailers is backed up into *last.
8260 */
8261 free(curmailers->id);
8262 curmailers = curmailers->next;
8263 free(*last);
8264 *last = curmailers;
8265 }
8266 }
8267
Willy Tarreau34eb6712011-10-24 18:15:04 +02008268 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008269 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008270 MEM_F_SHARED);
8271
Willy Tarreaubb925012009-07-23 13:36:36 +02008272 if (cfgerr > 0)
8273 err_code |= ERR_ALERT | ERR_FATAL;
8274 out:
8275 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008276}
8277
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008278/*
8279 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8280 * parsing sessions.
8281 */
8282void cfg_register_keywords(struct cfg_kw_list *kwl)
8283{
8284 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8285}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008286
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008287/*
8288 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8289 */
8290void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8291{
8292 LIST_DEL(&kwl->list);
8293 LIST_INIT(&kwl->list);
8294}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008295
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008296/* this function register new section in the haproxy configuration file.
8297 * <section_name> is the name of this new section and <section_parser>
8298 * is the called parser. If two section declaration have the same name,
8299 * only the first declared is used.
8300 */
8301int cfg_register_section(char *section_name,
8302 int (*section_parser)(const char *, int, char **, int))
8303{
8304 struct cfg_section *cs;
8305
8306 cs = calloc(1, sizeof(*cs));
8307 if (!cs) {
8308 Alert("register section '%s': out of memory.\n", section_name);
8309 return 0;
8310 }
8311
8312 cs->section_name = section_name;
8313 cs->section_parser = section_parser;
8314
8315 LIST_ADDQ(&sections, &cs->list);
8316
8317 return 1;
8318}
8319
Willy Tarreaubaaee002006-06-26 02:48:02 +02008320/*
8321 * Local variables:
8322 * c-indent-level: 8
8323 * c-basic-offset: 8
8324 * End:
8325 */