blob: e08b8750b2b1151038d9d07a232f87f4e4da542e [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) {
1780 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1781 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1782 err_code |= ERR_WARN;
1783 }
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) {
1981 Warning("Parsing [%s:%d]: mailers '%s' has same name as another mailers (declared at %s:%d).\n",
1982 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
1983 err_code |= ERR_WARN;
1984 }
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 Tarreau7cbc9152014-03-15 08:17:08 +01002117 struct ebpt_node *node;
2118
Willy Tarreaubaaee002006-06-26 02:48:02 +02002119 if (!*args[1]) {
2120 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2121 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2122 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002123 err_code |= ERR_ALERT | ERR_ABORT;
2124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002125 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002126
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002127 err = invalid_char(args[1]);
2128 if (err) {
2129 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2130 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002131 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002132 }
2133
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002134 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
2135 curproxy = container_of(node, struct proxy, conf.by_name);
2136
2137 if (strcmp(curproxy->id, args[1]) != 0)
2138 break;
2139
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002140 /*
2141 * If there are two proxies with the same name only following
2142 * combinations are allowed:
2143 *
2144 * listen backend frontend ruleset
2145 * listen - - - -
2146 * backend - - OK -
2147 * frontend - OK - -
2148 * ruleset - - - -
2149 */
2150
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002151 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
2152 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02002153 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
2154 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2155 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02002156 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002157 }
2158 }
2159
Willy Tarreaubaaee002006-06-26 02:48:02 +02002160 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2161 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002162 err_code |= ERR_ALERT | ERR_ABORT;
2163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002164 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002165
Willy Tarreau97cb7802010-01-03 20:23:58 +01002166 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002167 curproxy->next = proxy;
2168 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002169 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2170 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002171 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002172 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002173 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002174 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002175
2176 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002177 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002178 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02002179
Willy Tarreau4348fad2012-09-20 16:48:07 +02002180 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2181
Willy Tarreau902636f2013-03-10 19:44:48 +01002182 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2183 if (errmsg && *errmsg) {
2184 indent_msg(&errmsg, 2);
2185 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002186 }
2187 else
2188 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2189 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002190 err_code |= ERR_FATAL;
2191 goto out;
2192 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002193
Willy Tarreau4348fad2012-09-20 16:48:07 +02002194 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002195 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002197 }
2198
2199 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002200 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002201 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002202
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002205 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002206 curproxy->no_options = defproxy.no_options;
2207 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002208 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002209 curproxy->except_net = defproxy.except_net;
2210 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002211 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002212 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002213
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002214 if (defproxy.fwdfor_hdr_len) {
2215 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2216 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2217 }
2218
Willy Tarreaub86db342009-11-30 11:50:16 +01002219 if (defproxy.orgto_hdr_len) {
2220 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2221 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2222 }
2223
Mark Lamourinec2247f02012-01-04 13:02:01 -05002224 if (defproxy.server_id_hdr_len) {
2225 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2226 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2227 }
2228
Willy Tarreau977b8e42006-12-29 14:19:17 +01002229 if (curproxy->cap & PR_CAP_FE) {
2230 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002231 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002232 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002233
2234 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002235 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2236 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002237
2238 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240
Willy Tarreau977b8e42006-12-29 14:19:17 +01002241 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002242 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002243 curproxy->fullconn = defproxy.fullconn;
2244 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002245 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002246 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002247
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002248 if (defproxy.check_req) {
2249 curproxy->check_req = calloc(1, defproxy.check_len);
2250 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2251 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002252 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002253
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002254 if (defproxy.expect_str) {
2255 curproxy->expect_str = strdup(defproxy.expect_str);
2256 if (defproxy.expect_regex) {
2257 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002258 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2259 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002260 }
2261 }
2262
Willy Tarreau67402132012-05-31 20:40:20 +02002263 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002264 if (defproxy.cookie_name)
2265 curproxy->cookie_name = strdup(defproxy.cookie_name);
2266 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002267 if (defproxy.cookie_domain)
2268 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002269
Willy Tarreau31936852010-10-06 16:59:56 +02002270 if (defproxy.cookie_maxidle)
2271 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2272
2273 if (defproxy.cookie_maxlife)
2274 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2275
Emeric Brun647caf12009-06-30 17:57:00 +02002276 if (defproxy.rdp_cookie_name)
2277 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2278 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2279
Willy Tarreau01732802007-11-01 22:48:15 +01002280 if (defproxy.url_param_name)
2281 curproxy->url_param_name = strdup(defproxy.url_param_name);
2282 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002283
Benoitaffb4812009-03-25 13:02:10 +01002284 if (defproxy.hh_name)
2285 curproxy->hh_name = strdup(defproxy.hh_name);
2286 curproxy->hh_len = defproxy.hh_len;
2287 curproxy->hh_match_domain = defproxy.hh_match_domain;
2288
Willy Tarreauef9a3602012-12-08 22:29:20 +01002289 if (defproxy.conn_src.iface_name)
2290 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2291 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002292 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002293#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002294 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002295#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002296 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002297
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002298 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002299 if (defproxy.capture_name)
2300 curproxy->capture_name = strdup(defproxy.capture_name);
2301 curproxy->capture_namelen = defproxy.capture_namelen;
2302 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002303 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002304
Willy Tarreau977b8e42006-12-29 14:19:17 +01002305 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002306 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002307 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002308 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002309 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002310 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002311 curproxy->mon_net = defproxy.mon_net;
2312 curproxy->mon_mask = defproxy.mon_mask;
2313 if (defproxy.monitor_uri)
2314 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2315 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002316 if (defproxy.defbe.name)
2317 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002318
2319 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002320 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2321 if (curproxy->conf.logformat_string &&
2322 curproxy->conf.logformat_string != default_http_log_format &&
2323 curproxy->conf.logformat_string != default_tcp_log_format &&
2324 curproxy->conf.logformat_string != clf_http_log_format)
2325 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2326
2327 if (defproxy.conf.lfs_file) {
2328 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2329 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2330 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002331 }
2332
2333 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002334 curproxy->timeout.connect = defproxy.timeout.connect;
2335 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002336 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002337 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002338 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002339 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002340 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002341 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002342 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002343 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002344 }
2345
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002347 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002348
2349 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002350 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002351 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002352 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002353 LIST_INIT(&node->list);
2354 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2355 }
2356
Willy Tarreau62a61232013-04-12 18:13:46 +02002357 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2358 if (curproxy->conf.uniqueid_format_string)
2359 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2360
Willy Tarreau094af4e2015-01-07 15:03:42 +01002361 if (defproxy.log_tag)
2362 curproxy->log_tag = strdup(defproxy.log_tag);
2363
Willy Tarreau62a61232013-04-12 18:13:46 +02002364 if (defproxy.conf.uif_file) {
2365 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2366 curproxy->conf.uif_line = defproxy.conf.uif_line;
2367 }
William Lallemanda73203e2012-03-12 12:48:57 +01002368
2369 /* copy default header unique id */
2370 if (defproxy.header_unique_id)
2371 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2372
William Lallemand82fe75c2012-10-23 10:25:10 +02002373 /* default compression options */
2374 if (defproxy.comp != NULL) {
2375 curproxy->comp = calloc(1, sizeof(struct comp));
2376 curproxy->comp->algos = defproxy.comp->algos;
2377 curproxy->comp->types = defproxy.comp->types;
2378 }
2379
Willy Tarreaubaaee002006-06-26 02:48:02 +02002380 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002381 curproxy->conf.used_listener_id = EB_ROOT;
2382 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002383
Simon Horman98637e52014-06-20 12:30:16 +09002384 if (defproxy.check_path)
2385 curproxy->check_path = strdup(defproxy.check_path);
2386 if (defproxy.check_command)
2387 curproxy->check_command = strdup(defproxy.check_command);
2388
Simon Horman9dc49962015-01-30 11:22:59 +09002389 if (defproxy.email_alert.mailers.name)
2390 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2391 if (defproxy.email_alert.from)
2392 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2393 if (defproxy.email_alert.to)
2394 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2395 if (defproxy.email_alert.myhostname)
2396 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002397 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002398
Willy Tarreau93893792009-07-23 13:19:11 +02002399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 }
2401 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2402 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002403 /* FIXME-20070101: we should do this too at the end of the
2404 * config parsing to free all default values.
2405 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002406 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002407 free(defproxy.check_command);
2408 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002409 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002410 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002411 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002412 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002413 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002414 free(defproxy.capture_name);
2415 free(defproxy.monitor_uri);
2416 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002417 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002418 free(defproxy.fwdfor_hdr_name);
2419 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002420 free(defproxy.orgto_hdr_name);
2421 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002422 free(defproxy.server_id_hdr_name);
2423 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002424 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002425 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002426 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002427 free(defproxy.expect_regex);
2428 defproxy.expect_regex = NULL;
2429 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002430
Willy Tarreau62a61232013-04-12 18:13:46 +02002431 if (defproxy.conf.logformat_string != default_http_log_format &&
2432 defproxy.conf.logformat_string != default_tcp_log_format &&
2433 defproxy.conf.logformat_string != clf_http_log_format)
2434 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002435
Willy Tarreau62a61232013-04-12 18:13:46 +02002436 free(defproxy.conf.uniqueid_format_string);
2437 free(defproxy.conf.lfs_file);
2438 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002439 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002440 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002441
Willy Tarreaua534fea2008-08-03 12:19:50 +02002442 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002443 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002444
Willy Tarreaubaaee002006-06-26 02:48:02 +02002445 /* we cannot free uri_auth because it might already be used */
2446 init_default_instance();
2447 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002448 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2449 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002450 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002451 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452 }
2453 else if (curproxy == NULL) {
2454 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
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 Tarreaua4312fa2013-04-02 16:34:32 +02002458
2459 /* update the current file and line being parsed */
2460 curproxy->conf.args.file = curproxy->conf.file;
2461 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002462
2463 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002464 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2465 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2466 if (err_code & ERR_FATAL)
2467 goto out;
2468 }
2469 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002470 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002471 int cur_arg;
2472
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 if (curproxy == &defproxy) {
2474 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002478 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002479 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002480
Willy Tarreau24709282013-03-10 21:32:12 +01002481 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002482 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002483 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002484 err_code |= ERR_ALERT | ERR_FATAL;
2485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002486 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002487
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002488 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002489
2490 /* use default settings for unix sockets */
2491 bind_conf->ux.uid = global.unix_bind.ux.uid;
2492 bind_conf->ux.gid = global.unix_bind.ux.gid;
2493 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002494
2495 /* NOTE: the following line might create several listeners if there
2496 * are comma-separated IPs or port ranges. So all further processing
2497 * will have to be applied to all listeners created after last_listen.
2498 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002499 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2500 if (errmsg && *errmsg) {
2501 indent_msg(&errmsg, 2);
2502 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002503 }
2504 else
2505 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2506 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002507 err_code |= ERR_ALERT | ERR_FATAL;
2508 goto out;
2509 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002510
Willy Tarreau4348fad2012-09-20 16:48:07 +02002511 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2512 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002513 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002514 }
2515
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002516 cur_arg = 2;
2517 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002518 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002519 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002520 char *err;
2521
Willy Tarreau26982662012-09-12 23:17:10 +02002522 kw = bind_find_kw(args[cur_arg]);
2523 if (kw) {
2524 char *err = NULL;
2525 int code;
2526
2527 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002528 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2529 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002530 cur_arg += 1 + kw->skip ;
2531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
2533 }
2534
Willy Tarreau4348fad2012-09-20 16:48:07 +02002535 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002536 err_code |= code;
2537
2538 if (code) {
2539 if (err && *err) {
2540 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002541 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002542 }
2543 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002544 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2545 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002546 if (code & ERR_FATAL) {
2547 free(err);
2548 cur_arg += 1 + kw->skip;
2549 goto out;
2550 }
2551 }
2552 free(err);
2553 cur_arg += 1 + kw->skip;
2554 continue;
2555 }
2556
Willy Tarreau8638f482012-09-18 18:01:17 +02002557 err = NULL;
2558 if (!bind_dumped) {
2559 bind_dump_kws(&err);
2560 indent_msg(&err, 4);
2561 bind_dumped = 1;
2562 }
2563
2564 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2565 file, linenum, args[0], args[1], args[cur_arg],
2566 err ? " Registered keywords :" : "", err ? err : "");
2567 free(err);
2568
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_ALERT | ERR_FATAL;
2570 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002571 }
Willy Tarreau93893792009-07-23 13:19:11 +02002572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002573 }
2574 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002575 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2577 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002578 err_code |= ERR_ALERT | ERR_FATAL;
2579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002581 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002582 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002583
Willy Tarreaubaaee002006-06-26 02:48:02 +02002584 /* flush useless bits */
2585 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002588 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002589 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002590 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002591
Willy Tarreau1c47f852006-07-09 08:22:27 +02002592 if (!*args[1]) {
2593 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2594 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002597 }
2598
Willy Tarreaua534fea2008-08-03 12:19:50 +02002599 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002600 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002601 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002602 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002603 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2604
Willy Tarreau93893792009-07-23 13:19:11 +02002605 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2608 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2609 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2610 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2611 else {
2612 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002613 err_code |= ERR_ALERT | ERR_FATAL;
2614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002615 }
2616 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002617 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002618 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002619
2620 if (curproxy == &defproxy) {
2621 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2622 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002623 err_code |= ERR_ALERT | ERR_FATAL;
2624 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002625 }
2626
2627 if (!*args[1]) {
2628 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2629 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002632 }
2633
2634 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002635 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002636
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002637 if (curproxy->uuid <= 0) {
2638 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002639 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002640 err_code |= ERR_ALERT | ERR_FATAL;
2641 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002642 }
2643
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002644 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2645 if (node) {
2646 struct proxy *target = container_of(node, struct proxy, conf.id);
2647 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2648 file, linenum, proxy_type_str(curproxy), curproxy->id,
2649 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
2652 }
2653 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002654 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002655 else if (!strcmp(args[0], "description")) {
2656 int i, len=0;
2657 char *d;
2658
Cyril Bonté99ed3272010-01-24 23:29:44 +01002659 if (curproxy == &defproxy) {
2660 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2661 file, linenum, args[0]);
2662 err_code |= ERR_ALERT | ERR_FATAL;
2663 goto out;
2664 }
2665
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002666 if (!*args[1]) {
2667 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2668 file, linenum, args[0]);
2669 return -1;
2670 }
2671
Willy Tarreau348acfe2014-04-14 15:00:39 +02002672 for (i = 1; *args[i]; i++)
2673 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002674
2675 d = (char *)calloc(1, len);
2676 curproxy->desc = d;
2677
Willy Tarreau348acfe2014-04-14 15:00:39 +02002678 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2679 for (i = 2; *args[i]; i++)
2680 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002681
2682 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002683 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2684 curproxy->state = PR_STSTOPPED;
2685 }
2686 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2687 curproxy->state = PR_STNEW;
2688 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002689 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2690 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002691 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002692
2693 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002694 unsigned int low, high;
2695
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002696 if (strcmp(args[cur_arg], "all") == 0) {
2697 set = 0;
2698 break;
2699 }
2700 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002701 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002702 }
2703 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002704 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002705 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002706 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002707 char *dash = strchr(args[cur_arg], '-');
2708
2709 low = high = str2uic(args[cur_arg]);
2710 if (dash)
2711 high = str2uic(dash + 1);
2712
2713 if (high < low) {
2714 unsigned int swap = low;
2715 low = high;
2716 high = swap;
2717 }
2718
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002719 if (low < 1 || high > LONGBITS) {
2720 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2721 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002722 err_code |= ERR_ALERT | ERR_FATAL;
2723 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002724 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002725 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002726 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002727 }
2728 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002729 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2730 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002731 err_code |= ERR_ALERT | ERR_FATAL;
2732 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002733 }
2734 cur_arg++;
2735 }
2736 curproxy->bind_proc = set;
2737 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002738 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002739 if (curproxy == &defproxy) {
2740 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002743 }
2744
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002745 err = invalid_char(args[1]);
2746 if (err) {
2747 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2748 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002749 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002750 }
2751
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002752 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002753 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2754 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002755 err_code |= ERR_ALERT | ERR_FATAL;
2756 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002757 }
2758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2760 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002761
Willy Tarreau977b8e42006-12-29 14:19:17 +01002762 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002763 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002764
Willy Tarreaubaaee002006-06-26 02:48:02 +02002765 if (*(args[1]) == 0) {
2766 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2767 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002770 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002771
Willy Tarreau67402132012-05-31 20:40:20 +02002772 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002773 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002774 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002775 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002776 curproxy->cookie_name = strdup(args[1]);
2777 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002778
Willy Tarreaubaaee002006-06-26 02:48:02 +02002779 cur_arg = 2;
2780 while (*(args[cur_arg])) {
2781 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002782 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002783 }
2784 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002785 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002786 }
2787 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002788 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002789 }
2790 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002791 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002792 }
2793 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002794 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002795 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002796 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002797 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002798 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002799 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002800 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002801 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002802 else if (!strcmp(args[cur_arg], "httponly")) {
2803 curproxy->ck_opts |= PR_CK_HTTPONLY;
2804 }
2805 else if (!strcmp(args[cur_arg], "secure")) {
2806 curproxy->ck_opts |= PR_CK_SECURE;
2807 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002808 else if (!strcmp(args[cur_arg], "domain")) {
2809 if (!*args[cur_arg + 1]) {
2810 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2811 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002812 err_code |= ERR_ALERT | ERR_FATAL;
2813 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002814 }
2815
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002816 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002817 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002818 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2819 " dots nor does not start with a dot."
2820 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002821 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002822 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002823 }
2824
2825 err = invalid_domainchar(args[cur_arg + 1]);
2826 if (err) {
2827 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2828 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002829 err_code |= ERR_ALERT | ERR_FATAL;
2830 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002831 }
2832
Willy Tarreau68a897b2009-12-03 23:28:34 +01002833 if (!curproxy->cookie_domain) {
2834 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2835 } else {
2836 /* one domain was already specified, add another one by
2837 * building the string which will be returned along with
2838 * the cookie.
2839 */
2840 char *new_ptr;
2841 int new_len = strlen(curproxy->cookie_domain) +
2842 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2843 new_ptr = malloc(new_len);
2844 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2845 free(curproxy->cookie_domain);
2846 curproxy->cookie_domain = new_ptr;
2847 }
Willy Tarreau31936852010-10-06 16:59:56 +02002848 cur_arg++;
2849 }
2850 else if (!strcmp(args[cur_arg], "maxidle")) {
2851 unsigned int maxidle;
2852 const char *res;
2853
2854 if (!*args[cur_arg + 1]) {
2855 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2856 file, linenum, args[cur_arg]);
2857 err_code |= ERR_ALERT | ERR_FATAL;
2858 goto out;
2859 }
2860
2861 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2862 if (res) {
2863 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2864 file, linenum, *res, args[cur_arg]);
2865 err_code |= ERR_ALERT | ERR_FATAL;
2866 goto out;
2867 }
2868 curproxy->cookie_maxidle = maxidle;
2869 cur_arg++;
2870 }
2871 else if (!strcmp(args[cur_arg], "maxlife")) {
2872 unsigned int maxlife;
2873 const char *res;
2874
2875 if (!*args[cur_arg + 1]) {
2876 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2877 file, linenum, args[cur_arg]);
2878 err_code |= ERR_ALERT | ERR_FATAL;
2879 goto out;
2880 }
2881
2882 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2883 if (res) {
2884 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2885 file, linenum, *res, args[cur_arg]);
2886 err_code |= ERR_ALERT | ERR_FATAL;
2887 goto out;
2888 }
2889 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002890 cur_arg++;
2891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002892 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002893 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 +02002894 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002895 err_code |= ERR_ALERT | ERR_FATAL;
2896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 }
2898 cur_arg++;
2899 }
Willy Tarreau67402132012-05-31 20:40:20 +02002900 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002901 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2902 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002903 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002904 }
2905
Willy Tarreau67402132012-05-31 20:40:20 +02002906 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002907 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2908 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002909 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002910 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002911
Willy Tarreau67402132012-05-31 20:40:20 +02002912 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002913 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2914 file, linenum);
2915 err_code |= ERR_ALERT | ERR_FATAL;
2916 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002917 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09002918 else if (!strcmp(args[0], "email-alert")) {
2919 if (*(args[1]) == 0) {
2920 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2921 file, linenum, args[0]);
2922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
2924 }
2925
2926 if (!strcmp(args[1], "from")) {
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.from);
2934 curproxy->email_alert.from = strdup(args[2]);
2935 }
2936 else if (!strcmp(args[1], "mailers")) {
2937 if (*(args[1]) == 0) {
2938 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2939 file, linenum, args[1]);
2940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
2942 }
2943 free(curproxy->email_alert.mailers.name);
2944 curproxy->email_alert.mailers.name = strdup(args[2]);
2945 }
2946 else if (!strcmp(args[1], "myhostname")) {
2947 if (*(args[1]) == 0) {
2948 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2949 file, linenum, args[1]);
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952 }
2953 free(curproxy->email_alert.myhostname);
2954 curproxy->email_alert.myhostname = strdup(args[2]);
2955 }
Simon Horman64e34162015-02-06 11:11:57 +09002956 else if (!strcmp(args[1], "level")) {
2957 curproxy->email_alert.level = get_log_level(args[2]);
2958 if (curproxy->email_alert.level < 0) {
2959 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
2960 file, linenum, args[1], args[2]);
2961 err_code |= ERR_ALERT | ERR_FATAL;
2962 goto out;
2963 }
2964 }
Simon Horman9dc49962015-01-30 11:22:59 +09002965 else if (!strcmp(args[1], "to")) {
2966 if (*(args[1]) == 0) {
2967 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2968 file, linenum, args[1]);
2969 err_code |= ERR_ALERT | ERR_FATAL;
2970 goto out;
2971 }
2972 free(curproxy->email_alert.to);
2973 curproxy->email_alert.to = strdup(args[2]);
2974 }
2975 else {
2976 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
2977 file, linenum, args[1]);
2978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
2980 }
Simon Horman64e34162015-02-06 11:11:57 +09002981 /* Indicate that the email_alert is at least partially configured */
2982 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09002983 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09002984 else if (!strcmp(args[0], "external-check")) {
2985 if (*(args[1]) == 0) {
2986 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2987 file, linenum, args[0]);
2988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
2990 }
2991
2992 if (!strcmp(args[1], "command")) {
2993 if (*(args[1]) == 0) {
2994 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2995 file, linenum, args[1]);
2996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
2998 }
2999 free(curproxy->check_command);
3000 curproxy->check_command = strdup(args[2]);
3001 }
3002 else if (!strcmp(args[1], "path")) {
3003 if (*(args[1]) == 0) {
3004 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3005 file, linenum, args[1]);
3006 err_code |= ERR_ALERT | ERR_FATAL;
3007 goto out;
3008 }
3009 free(curproxy->check_path);
3010 curproxy->check_path = strdup(args[2]);
3011 }
3012 else {
3013 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3014 file, linenum, args[1]);
3015 err_code |= ERR_ALERT | ERR_FATAL;
3016 goto out;
3017 }
3018 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003019 else if (!strcmp(args[0], "persist")) { /* persist */
3020 if (*(args[1]) == 0) {
3021 Alert("parsing [%s:%d] : missing persist method.\n",
3022 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003023 err_code |= ERR_ALERT | ERR_FATAL;
3024 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003025 }
3026
3027 if (!strncmp(args[1], "rdp-cookie", 10)) {
3028 curproxy->options2 |= PR_O2_RDPC_PRST;
3029
Emeric Brunb982a3d2010-01-04 15:45:53 +01003030 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003031 const char *beg, *end;
3032
3033 beg = args[1] + 11;
3034 end = strchr(beg, ')');
3035
3036 if (!end || end == beg) {
3037 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3038 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003041 }
3042
3043 free(curproxy->rdp_cookie_name);
3044 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3045 curproxy->rdp_cookie_len = end-beg;
3046 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003047 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003048 free(curproxy->rdp_cookie_name);
3049 curproxy->rdp_cookie_name = strdup("msts");
3050 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3051 }
3052 else { /* syntax */
3053 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3054 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003057 }
3058 }
3059 else {
3060 Alert("parsing [%s:%d] : unknown persist method.\n",
3061 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003062 err_code |= ERR_ALERT | ERR_FATAL;
3063 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003064 }
3065 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003067 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003068
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003069 if (curproxy == &defproxy) {
3070 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
3073 }
3074
Willy Tarreau977b8e42006-12-29 14:19:17 +01003075 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003076 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003077
Willy Tarreaubaaee002006-06-26 02:48:02 +02003078 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003079 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 }
3084 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003085 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 curproxy->appsession_name = strdup(args[1]);
3087 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3088 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003089 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3090 if (err) {
3091 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3092 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003093 err_code |= ERR_ALERT | ERR_FATAL;
3094 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003095 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003096 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003097
Willy Tarreau51041c72007-09-09 21:56:53 +02003098 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3099 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003100 err_code |= ERR_ALERT | ERR_ABORT;
3101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003102 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003103
3104 cur_arg = 6;
3105 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003106 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3107 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003108 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003109 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003110 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003111 } else if (!strcmp(args[cur_arg], "prefix")) {
3112 curproxy->options2 |= PR_O2_AS_PFX;
3113 } else if (!strcmp(args[cur_arg], "mode")) {
3114 if (!*args[cur_arg + 1]) {
3115 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3116 file, linenum, args[0], args[cur_arg]);
3117 err_code |= ERR_ALERT | ERR_FATAL;
3118 goto out;
3119 }
3120
3121 cur_arg++;
3122 if (!strcmp(args[cur_arg], "query-string")) {
3123 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3124 curproxy->options2 |= PR_O2_AS_M_QS;
3125 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3126 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3127 curproxy->options2 |= PR_O2_AS_M_PP;
3128 } else {
3129 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3130 err_code |= ERR_ALERT | ERR_FATAL;
3131 goto out;
3132 }
3133 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003134 cur_arg++;
3135 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136 } /* Url App Session */
3137 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003138 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003139 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003140
Willy Tarreaubaaee002006-06-26 02:48:02 +02003141 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003142 if (curproxy == &defproxy) {
3143 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3144 err_code |= ERR_ALERT | ERR_FATAL;
3145 goto out;
3146 }
3147
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 if (*(args[4]) == 0) {
3149 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3150 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003151 err_code |= ERR_ALERT | ERR_FATAL;
3152 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003153 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003154 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 curproxy->capture_name = strdup(args[2]);
3156 curproxy->capture_namelen = strlen(curproxy->capture_name);
3157 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 curproxy->to_log |= LW_COOKIE;
3159 }
3160 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3161 struct cap_hdr *hdr;
3162
3163 if (curproxy == &defproxy) {
3164 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 +02003165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167 }
3168
3169 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3170 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3171 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003172 err_code |= ERR_ALERT | ERR_FATAL;
3173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003174 }
3175
3176 hdr = calloc(sizeof(struct cap_hdr), 1);
3177 hdr->next = curproxy->req_cap;
3178 hdr->name = strdup(args[3]);
3179 hdr->namelen = strlen(args[3]);
3180 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003181 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003182 hdr->index = curproxy->nb_req_cap++;
3183 curproxy->req_cap = hdr;
3184 curproxy->to_log |= LW_REQHDR;
3185 }
3186 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3187 struct cap_hdr *hdr;
3188
3189 if (curproxy == &defproxy) {
3190 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 +02003191 err_code |= ERR_ALERT | ERR_FATAL;
3192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003193 }
3194
3195 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3196 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3197 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003198 err_code |= ERR_ALERT | ERR_FATAL;
3199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003200 }
3201 hdr = calloc(sizeof(struct cap_hdr), 1);
3202 hdr->next = curproxy->rsp_cap;
3203 hdr->name = strdup(args[3]);
3204 hdr->namelen = strlen(args[3]);
3205 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003206 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 hdr->index = curproxy->nb_rsp_cap++;
3208 curproxy->rsp_cap = hdr;
3209 curproxy->to_log |= LW_RSPHDR;
3210 }
3211 else {
3212 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3213 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003214 err_code |= ERR_ALERT | ERR_FATAL;
3215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003216 }
3217 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003218 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003219 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003220 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003221
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 if (*(args[1]) == 0) {
3223 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3224 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003225 err_code |= ERR_ALERT | ERR_FATAL;
3226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 }
3228 curproxy->conn_retries = atol(args[1]);
3229 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003230 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003231 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003232
3233 if (curproxy == &defproxy) {
3234 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3235 err_code |= ERR_ALERT | ERR_FATAL;
3236 goto out;
3237 }
3238
Willy Tarreau20b0de52012-12-24 15:45:22 +01003239 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3240 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3241 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3242 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003243 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003244 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3245 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 +01003246 file, linenum, args[0]);
3247 err_code |= ERR_WARN;
3248 }
3249
Willy Tarreauff011f22011-01-06 17:51:27 +01003250 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003251
Willy Tarreauff011f22011-01-06 17:51:27 +01003252 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003253 err_code |= ERR_ALERT | ERR_ABORT;
3254 goto out;
3255 }
3256
Willy Tarreau5002f572014-04-23 01:32:02 +02003257 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003258 err_code |= warnif_cond_conflicts(rule->cond,
3259 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3260 file, linenum);
3261
Willy Tarreauff011f22011-01-06 17:51:27 +01003262 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003263 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003264 else if (!strcmp(args[0], "http-response")) { /* response access control */
3265 struct http_res_rule *rule;
3266
3267 if (curproxy == &defproxy) {
3268 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3269 err_code |= ERR_ALERT | ERR_FATAL;
3270 goto out;
3271 }
3272
3273 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3274 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3275 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3276 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3277 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3278 file, linenum, args[0]);
3279 err_code |= ERR_WARN;
3280 }
3281
3282 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3283
3284 if (!rule) {
3285 err_code |= ERR_ALERT | ERR_ABORT;
3286 goto out;
3287 }
3288
3289 err_code |= warnif_cond_conflicts(rule->cond,
3290 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3291 file, linenum);
3292
3293 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3294 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003295 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3296 /* set the header name and length into the proxy structure */
3297 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3298 err_code |= ERR_WARN;
3299
3300 if (!*args[1]) {
3301 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3302 file, linenum, args[0]);
3303 err_code |= ERR_ALERT | ERR_FATAL;
3304 goto out;
3305 }
3306
3307 /* set the desired header name */
3308 free(curproxy->server_id_hdr_name);
3309 curproxy->server_id_hdr_name = strdup(args[1]);
3310 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3311 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003312 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003313 struct http_req_rule *rule;
3314
Willy Tarreaub099aca2008-10-12 17:26:37 +02003315 if (curproxy == &defproxy) {
3316 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003317 err_code |= ERR_ALERT | ERR_FATAL;
3318 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003319 }
3320
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003321 /* emulate "block" using "http-request block". Since these rules are supposed to
3322 * be processed before all http-request rules, we put them into their own list
3323 * and will insert them at the end.
3324 */
3325 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3326 if (!rule) {
3327 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003328 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003329 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003330 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3331 err_code |= warnif_cond_conflicts(rule->cond,
3332 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3333 file, linenum);
3334 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003335
3336 if (!already_warned(WARN_BLOCK_DEPRECATED))
3337 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]);
3338
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003339 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003340 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003341 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003342
Cyril Bonté99ed3272010-01-24 23:29:44 +01003343 if (curproxy == &defproxy) {
3344 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3345 err_code |= ERR_ALERT | ERR_FATAL;
3346 goto out;
3347 }
3348
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003349 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003350 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3351 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003352 err_code |= ERR_ALERT | ERR_FATAL;
3353 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003354 }
3355
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003356 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003357 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003358 err_code |= warnif_cond_conflicts(rule->cond,
3359 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3360 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003361 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003362 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003363 struct switching_rule *rule;
3364
Willy Tarreaub099aca2008-10-12 17:26:37 +02003365 if (curproxy == &defproxy) {
3366 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003367 err_code |= ERR_ALERT | ERR_FATAL;
3368 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003369 }
3370
Willy Tarreau55ea7572007-06-17 19:56:27 +02003371 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003372 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003373
3374 if (*(args[1]) == 0) {
3375 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003376 err_code |= ERR_ALERT | ERR_FATAL;
3377 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003378 }
3379
Willy Tarreauf51658d2014-04-23 01:21:56 +02003380 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3381 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3382 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3383 file, linenum, errmsg);
3384 err_code |= ERR_ALERT | ERR_FATAL;
3385 goto out;
3386 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003387
Willy Tarreauf51658d2014-04-23 01:21:56 +02003388 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003389 }
3390
3391 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3392 rule->cond = cond;
3393 rule->be.name = strdup(args[1]);
3394 LIST_INIT(&rule->list);
3395 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3396 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003397 else if (strcmp(args[0], "use-server") == 0) {
3398 struct server_rule *rule;
3399
3400 if (curproxy == &defproxy) {
3401 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3402 err_code |= ERR_ALERT | ERR_FATAL;
3403 goto out;
3404 }
3405
3406 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3407 err_code |= ERR_WARN;
3408
3409 if (*(args[1]) == 0) {
3410 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3411 err_code |= ERR_ALERT | ERR_FATAL;
3412 goto out;
3413 }
3414
3415 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3416 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3417 file, linenum, args[0]);
3418 err_code |= ERR_ALERT | ERR_FATAL;
3419 goto out;
3420 }
3421
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003422 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3423 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3424 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003425 err_code |= ERR_ALERT | ERR_FATAL;
3426 goto out;
3427 }
3428
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003429 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003430
3431 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3432 rule->cond = cond;
3433 rule->srv.name = strdup(args[1]);
3434 LIST_INIT(&rule->list);
3435 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3436 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3437 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003438 else if ((!strcmp(args[0], "force-persist")) ||
3439 (!strcmp(args[0], "ignore-persist"))) {
3440 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003441
3442 if (curproxy == &defproxy) {
3443 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3444 err_code |= ERR_ALERT | ERR_FATAL;
3445 goto out;
3446 }
3447
3448 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3449 err_code |= ERR_WARN;
3450
Willy Tarreauef6494c2010-01-28 17:12:36 +01003451 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003452 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3453 file, linenum, args[0]);
3454 err_code |= ERR_ALERT | ERR_FATAL;
3455 goto out;
3456 }
3457
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003458 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3459 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3460 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003461 err_code |= ERR_ALERT | ERR_FATAL;
3462 goto out;
3463 }
3464
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003465 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3466 * where force-persist is applied.
3467 */
3468 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003469
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003470 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003471 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003472 if (!strcmp(args[0], "force-persist")) {
3473 rule->type = PERSIST_TYPE_FORCE;
3474 } else {
3475 rule->type = PERSIST_TYPE_IGNORE;
3476 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003477 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003478 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003479 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003480 else if (!strcmp(args[0], "stick-table")) {
3481 int myidx = 1;
3482
Emeric Brun32da3c42010-09-23 18:39:19 +02003483 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003484 curproxy->table.type = (unsigned int)-1;
3485 while (*args[myidx]) {
3486 const char *err;
3487
3488 if (strcmp(args[myidx], "size") == 0) {
3489 myidx++;
3490 if (!*(args[myidx])) {
3491 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3492 file, linenum, args[myidx-1]);
3493 err_code |= ERR_ALERT | ERR_FATAL;
3494 goto out;
3495 }
3496 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3497 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3498 file, linenum, *err, args[myidx-1]);
3499 err_code |= ERR_ALERT | ERR_FATAL;
3500 goto out;
3501 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003502 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003503 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003504 else if (strcmp(args[myidx], "peers") == 0) {
3505 myidx++;
Godbach50523162013-12-11 19:48:57 +08003506 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003507 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3508 file, linenum, args[myidx-1]);
3509 err_code |= ERR_ALERT | ERR_FATAL;
3510 goto out;
Godbach50523162013-12-11 19:48:57 +08003511 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003512 curproxy->table.peers.name = strdup(args[myidx++]);
3513 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003514 else if (strcmp(args[myidx], "expire") == 0) {
3515 myidx++;
3516 if (!*(args[myidx])) {
3517 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3518 file, linenum, args[myidx-1]);
3519 err_code |= ERR_ALERT | ERR_FATAL;
3520 goto out;
3521 }
3522 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3523 if (err) {
3524 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3525 file, linenum, *err, args[myidx-1]);
3526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
3528 }
3529 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003530 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003531 }
3532 else if (strcmp(args[myidx], "nopurge") == 0) {
3533 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003534 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003535 }
3536 else if (strcmp(args[myidx], "type") == 0) {
3537 myidx++;
3538 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3539 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3540 file, linenum, args[myidx]);
3541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
3543 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003544 /* myidx already points to next arg */
3545 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003546 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003547 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003548 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003549
3550 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003551 nw = args[myidx];
3552 while (*nw) {
3553 /* the "store" keyword supports a comma-separated list */
3554 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003555 sa = NULL; /* store arg */
3556 while (*nw && *nw != ',') {
3557 if (*nw == '(') {
3558 *nw = 0;
3559 sa = ++nw;
3560 while (*nw != ')') {
3561 if (!*nw) {
3562 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3563 file, linenum, args[0], cw);
3564 err_code |= ERR_ALERT | ERR_FATAL;
3565 goto out;
3566 }
3567 nw++;
3568 }
3569 *nw = '\0';
3570 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003571 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003572 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003573 if (*nw)
3574 *nw++ = '\0';
3575 type = stktable_get_data_type(cw);
3576 if (type < 0) {
3577 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3578 file, linenum, args[0], cw);
3579 err_code |= ERR_ALERT | ERR_FATAL;
3580 goto out;
3581 }
Willy Tarreauac782882010-06-20 10:41:54 +02003582
3583 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3584 switch (err) {
3585 case PE_NONE: break;
3586 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003587 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3588 file, linenum, args[0], cw);
3589 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003590 break;
3591
3592 case PE_ARG_MISSING:
3593 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3594 file, linenum, args[0], cw);
3595 err_code |= ERR_ALERT | ERR_FATAL;
3596 goto out;
3597
3598 case PE_ARG_NOT_USED:
3599 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3600 file, linenum, args[0], cw);
3601 err_code |= ERR_ALERT | ERR_FATAL;
3602 goto out;
3603
3604 default:
3605 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3606 file, linenum, args[0], cw);
3607 err_code |= ERR_ALERT | ERR_FATAL;
3608 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003609 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003610 }
3611 myidx++;
3612 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003613 else {
3614 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3615 file, linenum, args[myidx]);
3616 err_code |= ERR_ALERT | ERR_FATAL;
3617 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003618 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003619 }
3620
3621 if (!curproxy->table.size) {
3622 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3623 file, linenum);
3624 err_code |= ERR_ALERT | ERR_FATAL;
3625 goto out;
3626 }
3627
3628 if (curproxy->table.type == (unsigned int)-1) {
3629 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3630 file, linenum);
3631 err_code |= ERR_ALERT | ERR_FATAL;
3632 goto out;
3633 }
3634 }
3635 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003636 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003637 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003638 int myidx = 0;
3639 const char *name = NULL;
3640 int flags;
3641
3642 if (curproxy == &defproxy) {
3643 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3644 err_code |= ERR_ALERT | ERR_FATAL;
3645 goto out;
3646 }
3647
3648 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3649 err_code |= ERR_WARN;
3650 goto out;
3651 }
3652
3653 myidx++;
3654 if ((strcmp(args[myidx], "store") == 0) ||
3655 (strcmp(args[myidx], "store-request") == 0)) {
3656 myidx++;
3657 flags = STK_IS_STORE;
3658 }
3659 else if (strcmp(args[myidx], "store-response") == 0) {
3660 myidx++;
3661 flags = STK_IS_STORE | STK_ON_RSP;
3662 }
3663 else if (strcmp(args[myidx], "match") == 0) {
3664 myidx++;
3665 flags = STK_IS_MATCH;
3666 }
3667 else if (strcmp(args[myidx], "on") == 0) {
3668 myidx++;
3669 flags = STK_IS_MATCH | STK_IS_STORE;
3670 }
3671 else {
3672 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
3675 }
3676
3677 if (*(args[myidx]) == 0) {
3678 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3679 err_code |= ERR_ALERT | ERR_FATAL;
3680 goto out;
3681 }
3682
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003683 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003684 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003685 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003686 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003687 err_code |= ERR_ALERT | ERR_FATAL;
3688 goto out;
3689 }
3690
3691 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003692 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3693 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3694 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003695 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003696 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003697 goto out;
3698 }
3699 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003700 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3701 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3702 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003703 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003704 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003705 goto out;
3706 }
3707 }
3708
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003709 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003710 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003711
Emeric Brunb982a3d2010-01-04 15:45:53 +01003712 if (strcmp(args[myidx], "table") == 0) {
3713 myidx++;
3714 name = args[myidx++];
3715 }
3716
Willy Tarreauef6494c2010-01-28 17:12:36 +01003717 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003718 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3719 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3720 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003721 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003722 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003723 goto out;
3724 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003725 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003726 else if (*(args[myidx])) {
3727 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3728 file, linenum, args[0], args[myidx]);
3729 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003730 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003731 goto out;
3732 }
Emeric Brun97679e72010-09-23 17:56:44 +02003733 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003734 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003735 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003736 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003737
Emeric Brunb982a3d2010-01-04 15:45:53 +01003738 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3739 rule->cond = cond;
3740 rule->expr = expr;
3741 rule->flags = flags;
3742 rule->table.name = name ? strdup(name) : NULL;
3743 LIST_INIT(&rule->list);
3744 if (flags & STK_ON_RSP)
3745 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3746 else
3747 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3748 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003749 else if (!strcmp(args[0], "stats")) {
3750 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3751 curproxy->uri_auth = NULL; /* we must detach from the default config */
3752
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003753 if (!*args[1]) {
3754 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003755 } else if (!strcmp(args[1], "admin")) {
3756 struct stats_admin_rule *rule;
3757
3758 if (curproxy == &defproxy) {
3759 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
3762 }
3763
3764 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3765 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3766 err_code |= ERR_ALERT | ERR_ABORT;
3767 goto out;
3768 }
3769
3770 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3771 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3772 file, linenum, args[0], args[1]);
3773 err_code |= ERR_ALERT | ERR_FATAL;
3774 goto out;
3775 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003776 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3777 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3778 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003779 err_code |= ERR_ALERT | ERR_FATAL;
3780 goto out;
3781 }
3782
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003783 err_code |= warnif_cond_conflicts(cond,
3784 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3785 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003786
3787 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3788 rule->cond = cond;
3789 LIST_INIT(&rule->list);
3790 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003791 } else if (!strcmp(args[1], "uri")) {
3792 if (*(args[2]) == 0) {
3793 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003794 err_code |= ERR_ALERT | ERR_FATAL;
3795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003796 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3797 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003798 err_code |= ERR_ALERT | ERR_ABORT;
3799 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003800 }
3801 } else if (!strcmp(args[1], "realm")) {
3802 if (*(args[2]) == 0) {
3803 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003804 err_code |= ERR_ALERT | ERR_FATAL;
3805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003806 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3807 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003808 err_code |= ERR_ALERT | ERR_ABORT;
3809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003811 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003812 unsigned interval;
3813
3814 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3815 if (err) {
3816 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3817 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003820 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3821 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003822 err_code |= ERR_ALERT | ERR_ABORT;
3823 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003824 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003825 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003826 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003827
3828 if (curproxy == &defproxy) {
3829 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
3832 }
3833
3834 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3835 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3836 err_code |= ERR_ALERT | ERR_ABORT;
3837 goto out;
3838 }
3839
Willy Tarreauff011f22011-01-06 17:51:27 +01003840 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3841 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003842 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3843 file, linenum, args[0]);
3844 err_code |= ERR_WARN;
3845 }
3846
Willy Tarreauff011f22011-01-06 17:51:27 +01003847 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003848
Willy Tarreauff011f22011-01-06 17:51:27 +01003849 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003850 err_code |= ERR_ALERT | ERR_ABORT;
3851 goto out;
3852 }
3853
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003854 err_code |= warnif_cond_conflicts(rule->cond,
3855 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3856 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003857 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003858
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 } else if (!strcmp(args[1], "auth")) {
3860 if (*(args[2]) == 0) {
3861 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003864 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3865 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003866 err_code |= ERR_ALERT | ERR_ABORT;
3867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 }
3869 } else if (!strcmp(args[1], "scope")) {
3870 if (*(args[2]) == 0) {
3871 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003874 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3875 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003876 err_code |= ERR_ALERT | ERR_ABORT;
3877 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003878 }
3879 } else if (!strcmp(args[1], "enable")) {
3880 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3881 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003882 err_code |= ERR_ALERT | ERR_ABORT;
3883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003884 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003885 } else if (!strcmp(args[1], "hide-version")) {
3886 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3887 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003888 err_code |= ERR_ALERT | ERR_ABORT;
3889 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003890 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003891 } else if (!strcmp(args[1], "show-legends")) {
3892 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3893 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3894 err_code |= ERR_ALERT | ERR_ABORT;
3895 goto out;
3896 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003897 } else if (!strcmp(args[1], "show-node")) {
3898
3899 if (*args[2]) {
3900 int i;
3901 char c;
3902
3903 for (i=0; args[2][i]; i++) {
3904 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003905 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3906 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003907 break;
3908 }
3909
3910 if (!i || args[2][i]) {
3911 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3912 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3913 file, linenum, args[0], args[1]);
3914 err_code |= ERR_ALERT | ERR_FATAL;
3915 goto out;
3916 }
3917 }
3918
3919 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3920 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3921 err_code |= ERR_ALERT | ERR_ABORT;
3922 goto out;
3923 }
3924 } else if (!strcmp(args[1], "show-desc")) {
3925 char *desc = NULL;
3926
3927 if (*args[2]) {
3928 int i, len=0;
3929 char *d;
3930
Willy Tarreau348acfe2014-04-14 15:00:39 +02003931 for (i = 2; *args[i]; i++)
3932 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003933
3934 desc = d = (char *)calloc(1, len);
3935
Willy Tarreau348acfe2014-04-14 15:00:39 +02003936 d += snprintf(d, desc + len - d, "%s", args[2]);
3937 for (i = 3; *args[i]; i++)
3938 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003939 }
3940
3941 if (!*args[2] && !global.desc)
3942 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3943 file, linenum, args[1]);
3944 else {
3945 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3946 free(desc);
3947 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3948 err_code |= ERR_ALERT | ERR_ABORT;
3949 goto out;
3950 }
3951 free(desc);
3952 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003953 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003954stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003955 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 +01003956 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003959 }
3960 }
3961 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003962 int optnum;
3963
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003964 if (*(args[1]) == '\0') {
3965 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3966 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003967 err_code |= ERR_ALERT | ERR_FATAL;
3968 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003969 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003970
3971 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3972 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003973 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3974 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3975 file, linenum, cfg_opts[optnum].name);
3976 err_code |= ERR_ALERT | ERR_FATAL;
3977 goto out;
3978 }
Willy Tarreau93893792009-07-23 13:19:11 +02003979 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3980 err_code |= ERR_WARN;
3981 goto out;
3982 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003983
Willy Tarreau3842f002009-06-14 11:39:52 +02003984 curproxy->no_options &= ~cfg_opts[optnum].val;
3985 curproxy->options &= ~cfg_opts[optnum].val;
3986
3987 switch (kwm) {
3988 case KWM_STD:
3989 curproxy->options |= cfg_opts[optnum].val;
3990 break;
3991 case KWM_NO:
3992 curproxy->no_options |= cfg_opts[optnum].val;
3993 break;
3994 case KWM_DEF: /* already cleared */
3995 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003996 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003997
Willy Tarreau93893792009-07-23 13:19:11 +02003998 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003999 }
4000 }
4001
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004002 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4003 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004004 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4005 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4006 file, linenum, cfg_opts2[optnum].name);
4007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
4009 }
Willy Tarreau93893792009-07-23 13:19:11 +02004010 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4011 err_code |= ERR_WARN;
4012 goto out;
4013 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004014
Willy Tarreau3842f002009-06-14 11:39:52 +02004015 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4016 curproxy->options2 &= ~cfg_opts2[optnum].val;
4017
4018 switch (kwm) {
4019 case KWM_STD:
4020 curproxy->options2 |= cfg_opts2[optnum].val;
4021 break;
4022 case KWM_NO:
4023 curproxy->no_options2 |= cfg_opts2[optnum].val;
4024 break;
4025 case KWM_DEF: /* already cleared */
4026 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004027 }
Willy Tarreau93893792009-07-23 13:19:11 +02004028 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004029 }
4030 }
4031
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004032 /* HTTP options override each other. They can be cancelled using
4033 * "no option xxx" which only switches to default mode if the mode
4034 * was this one (useful for cancelling options set in defaults
4035 * sections).
4036 */
4037 if (strcmp(args[1], "httpclose") == 0) {
4038 if (kwm == KWM_STD) {
4039 curproxy->options &= ~PR_O_HTTP_MODE;
4040 curproxy->options |= PR_O_HTTP_PCL;
4041 goto out;
4042 }
4043 else if (kwm == KWM_NO) {
4044 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4045 curproxy->options &= ~PR_O_HTTP_MODE;
4046 goto out;
4047 }
4048 }
4049 else if (strcmp(args[1], "forceclose") == 0) {
4050 if (kwm == KWM_STD) {
4051 curproxy->options &= ~PR_O_HTTP_MODE;
4052 curproxy->options |= PR_O_HTTP_FCL;
4053 goto out;
4054 }
4055 else if (kwm == KWM_NO) {
4056 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4057 curproxy->options &= ~PR_O_HTTP_MODE;
4058 goto out;
4059 }
4060 }
4061 else if (strcmp(args[1], "http-server-close") == 0) {
4062 if (kwm == KWM_STD) {
4063 curproxy->options &= ~PR_O_HTTP_MODE;
4064 curproxy->options |= PR_O_HTTP_SCL;
4065 goto out;
4066 }
4067 else if (kwm == KWM_NO) {
4068 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4069 curproxy->options &= ~PR_O_HTTP_MODE;
4070 goto out;
4071 }
4072 }
4073 else if (strcmp(args[1], "http-keep-alive") == 0) {
4074 if (kwm == KWM_STD) {
4075 curproxy->options &= ~PR_O_HTTP_MODE;
4076 curproxy->options |= PR_O_HTTP_KAL;
4077 goto out;
4078 }
4079 else if (kwm == KWM_NO) {
4080 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4081 curproxy->options &= ~PR_O_HTTP_MODE;
4082 goto out;
4083 }
4084 }
4085 else if (strcmp(args[1], "http-tunnel") == 0) {
4086 if (kwm == KWM_STD) {
4087 curproxy->options &= ~PR_O_HTTP_MODE;
4088 curproxy->options |= PR_O_HTTP_TUN;
4089 goto out;
4090 }
4091 else if (kwm == KWM_NO) {
4092 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4093 curproxy->options &= ~PR_O_HTTP_MODE;
4094 goto out;
4095 }
4096 }
4097
Joseph Lynch726ab712015-05-11 23:25:34 -07004098 /* Redispatch can take an integer argument that control when the
4099 * resispatch occurs. All values are relative to the retries option.
4100 * This can be cancelled using "no option xxx".
4101 */
4102 if (strcmp(args[1], "redispatch") == 0) {
4103 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4104 err_code |= ERR_WARN;
4105 goto out;
4106 }
4107
4108 curproxy->no_options &= ~PR_O_REDISP;
4109 curproxy->options &= ~PR_O_REDISP;
4110
4111 switch (kwm) {
4112 case KWM_STD:
4113 curproxy->options |= PR_O_REDISP;
4114 curproxy->redispatch_after = -1;
4115 if(*args[2]) {
4116 curproxy->redispatch_after = atol(args[2]);
4117 }
4118 break;
4119 case KWM_NO:
4120 curproxy->no_options |= PR_O_REDISP;
4121 curproxy->redispatch_after = 0;
4122 break;
4123 case KWM_DEF: /* already cleared */
4124 break;
4125 }
4126 goto out;
4127 }
4128
Willy Tarreau3842f002009-06-14 11:39:52 +02004129 if (kwm != KWM_STD) {
4130 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004131 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004132 err_code |= ERR_ALERT | ERR_FATAL;
4133 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004134 }
4135
Emeric Brun3a058f32009-06-30 18:26:00 +02004136 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004137 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004138 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004139 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004140 if (*(args[2]) != '\0') {
4141 if (!strcmp(args[2], "clf")) {
4142 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004143 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004144 } else {
4145 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02004146 err_code |= ERR_ALERT | ERR_FATAL;
4147 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004148 }
4149 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004150 if (curproxy->conf.logformat_string != default_http_log_format &&
4151 curproxy->conf.logformat_string != default_tcp_log_format &&
4152 curproxy->conf.logformat_string != clf_http_log_format)
4153 free(curproxy->conf.logformat_string);
4154 curproxy->conf.logformat_string = logformat;
4155
4156 free(curproxy->conf.lfs_file);
4157 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4158 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004159 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004160 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004161 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004162 if (curproxy->conf.logformat_string != default_http_log_format &&
4163 curproxy->conf.logformat_string != default_tcp_log_format &&
4164 curproxy->conf.logformat_string != clf_http_log_format)
4165 free(curproxy->conf.logformat_string);
4166 curproxy->conf.logformat_string = default_tcp_log_format;
4167
4168 free(curproxy->conf.lfs_file);
4169 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4170 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004171 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004172 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004173 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004174 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004175 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004176
4177 if (curproxy->cap & PR_CAP_FE)
4178 curproxy->options |= PR_O_TCP_CLI_KA;
4179 if (curproxy->cap & PR_CAP_BE)
4180 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004181 }
4182 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004183 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004184 err_code |= ERR_WARN;
4185
Willy Tarreaubaaee002006-06-26 02:48:02 +02004186 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004187 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004188 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004189 curproxy->options2 &= ~PR_O2_CHK_ANY;
4190 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004191 if (!*args[2]) { /* no argument */
4192 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4193 curproxy->check_len = strlen(DEF_CHECK_REQ);
4194 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004195 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004196 curproxy->check_req = (char *)malloc(reqlen);
4197 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004198 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004199 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004200 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004201 if (*args[4])
4202 reqlen += strlen(args[4]);
4203 else
4204 reqlen += strlen("HTTP/1.0");
4205
4206 curproxy->check_req = (char *)malloc(reqlen);
4207 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004208 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004209 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004210 }
4211 else if (!strcmp(args[1], "ssl-hello-chk")) {
4212 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004213 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004214 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004215
Willy Tarreaua534fea2008-08-03 12:19:50 +02004216 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004217 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004218 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004219 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004220 }
Willy Tarreau23677902007-05-08 23:50:35 +02004221 else if (!strcmp(args[1], "smtpchk")) {
4222 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004223 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004224 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004225 curproxy->options2 &= ~PR_O2_CHK_ANY;
4226 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004227
4228 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4229 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4230 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4231 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4232 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4233 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4234 curproxy->check_req = (char *)malloc(reqlen);
4235 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4236 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4237 } else {
4238 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4239 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4240 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4241 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4242 }
4243 }
4244 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004245 else if (!strcmp(args[1], "pgsql-check")) {
4246 /* use PostgreSQL request to check servers' health */
4247 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4248 err_code |= ERR_WARN;
4249
4250 free(curproxy->check_req);
4251 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004252 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004253 curproxy->options2 |= PR_O2_PGSQL_CHK;
4254
4255 if (*(args[2])) {
4256 int cur_arg = 2;
4257
4258 while (*(args[cur_arg])) {
4259 if (strcmp(args[cur_arg], "user") == 0) {
4260 char * packet;
4261 uint32_t packet_len;
4262 uint32_t pv;
4263
4264 /* suboption header - needs additional argument for it */
4265 if (*(args[cur_arg+1]) == 0) {
4266 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4267 file, linenum, args[0], args[1], args[cur_arg]);
4268 err_code |= ERR_ALERT | ERR_FATAL;
4269 goto out;
4270 }
4271
4272 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4273 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4274 pv = htonl(0x30000); /* protocol version 3.0 */
4275
4276 packet = (char*) calloc(1, packet_len);
4277
4278 memcpy(packet + 4, &pv, 4);
4279
4280 /* copy "user" */
4281 memcpy(packet + 8, "user", 4);
4282
4283 /* copy username */
4284 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4285
4286 free(curproxy->check_req);
4287 curproxy->check_req = packet;
4288 curproxy->check_len = packet_len;
4289
4290 packet_len = htonl(packet_len);
4291 memcpy(packet, &packet_len, 4);
4292 cur_arg += 2;
4293 } else {
4294 /* unknown suboption - catchall */
4295 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4296 file, linenum, args[0], args[1]);
4297 err_code |= ERR_ALERT | ERR_FATAL;
4298 goto out;
4299 }
4300 } /* end while loop */
4301 }
4302 }
4303
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004304 else if (!strcmp(args[1], "redis-check")) {
4305 /* use REDIS PING request to check servers' health */
4306 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4307 err_code |= ERR_WARN;
4308
4309 free(curproxy->check_req);
4310 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004311 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004312 curproxy->options2 |= PR_O2_REDIS_CHK;
4313
4314 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4315 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4316 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4317 }
4318
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004319 else if (!strcmp(args[1], "mysql-check")) {
4320 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004321 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4322 err_code |= ERR_WARN;
4323
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004324 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004325 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004326 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004327 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004328
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004329 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004330 * const char mysql40_client_auth_pkt[] = {
4331 * "\x0e\x00\x00" // packet length
4332 * "\x01" // packet number
4333 * "\x00\x00" // client capabilities
4334 * "\x00\x00\x01" // max packet
4335 * "haproxy\x00" // username (null terminated string)
4336 * "\x00" // filler (always 0x00)
4337 * "\x01\x00\x00" // packet length
4338 * "\x00" // packet number
4339 * "\x01" // COM_QUIT command
4340 * };
4341 */
4342
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004343 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4344 * const char mysql41_client_auth_pkt[] = {
4345 * "\x0e\x00\x00\" // packet length
4346 * "\x01" // packet number
4347 * "\x00\x00\x00\x00" // client capabilities
4348 * "\x00\x00\x00\x01" // max packet
4349 * "\x21" // character set (UTF-8)
4350 * char[23] // All zeroes
4351 * "haproxy\x00" // username (null terminated string)
4352 * "\x00" // filler (always 0x00)
4353 * "\x01\x00\x00" // packet length
4354 * "\x00" // packet number
4355 * "\x01" // COM_QUIT command
4356 * };
4357 */
4358
4359
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004360 if (*(args[2])) {
4361 int cur_arg = 2;
4362
4363 while (*(args[cur_arg])) {
4364 if (strcmp(args[cur_arg], "user") == 0) {
4365 char *mysqluser;
4366 int packetlen, reqlen, userlen;
4367
4368 /* suboption header - needs additional argument for it */
4369 if (*(args[cur_arg+1]) == 0) {
4370 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4371 file, linenum, args[0], args[1], args[cur_arg]);
4372 err_code |= ERR_ALERT | ERR_FATAL;
4373 goto out;
4374 }
4375 mysqluser = args[cur_arg + 1];
4376 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004377
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004378 if (*(args[cur_arg+2])) {
4379 if (!strcmp(args[cur_arg+2], "post-41")) {
4380 packetlen = userlen + 7 + 27;
4381 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004382
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004383 free(curproxy->check_req);
4384 curproxy->check_req = (char *)calloc(1, reqlen);
4385 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004386
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004387 snprintf(curproxy->check_req, 4, "%c%c%c",
4388 ((unsigned char) packetlen & 0xff),
4389 ((unsigned char) (packetlen >> 8) & 0xff),
4390 ((unsigned char) (packetlen >> 16) & 0xff));
4391
4392 curproxy->check_req[3] = 1;
4393 curproxy->check_req[5] = 130;
4394 curproxy->check_req[11] = 1;
4395 curproxy->check_req[12] = 33;
4396 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4397 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4398 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4399 cur_arg += 3;
4400 } else {
4401 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4402 err_code |= ERR_ALERT | ERR_FATAL;
4403 goto out;
4404 }
4405 } else {
4406 packetlen = userlen + 7;
4407 reqlen = packetlen + 9;
4408
4409 free(curproxy->check_req);
4410 curproxy->check_req = (char *)calloc(1, reqlen);
4411 curproxy->check_len = reqlen;
4412
4413 snprintf(curproxy->check_req, 4, "%c%c%c",
4414 ((unsigned char) packetlen & 0xff),
4415 ((unsigned char) (packetlen >> 8) & 0xff),
4416 ((unsigned char) (packetlen >> 16) & 0xff));
4417
4418 curproxy->check_req[3] = 1;
4419 curproxy->check_req[5] = 128;
4420 curproxy->check_req[8] = 1;
4421 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4422 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4423 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4424 cur_arg += 2;
4425 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004426 } else {
4427 /* unknown suboption - catchall */
4428 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4429 file, linenum, args[0], args[1]);
4430 err_code |= ERR_ALERT | ERR_FATAL;
4431 goto out;
4432 }
4433 } /* end while loop */
4434 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004435 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004436 else if (!strcmp(args[1], "ldap-check")) {
4437 /* use LDAP request to check servers' health */
4438 free(curproxy->check_req);
4439 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004440 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004441 curproxy->options2 |= PR_O2_LDAP_CHK;
4442
4443 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4444 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4445 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4446 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004447 else if (!strcmp(args[1], "tcp-check")) {
4448 /* use raw TCPCHK send/expect to check servers' health */
4449 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4450 err_code |= ERR_WARN;
4451
4452 free(curproxy->check_req);
4453 curproxy->check_req = NULL;
4454 curproxy->options2 &= ~PR_O2_CHK_ANY;
4455 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4456 }
Simon Horman98637e52014-06-20 12:30:16 +09004457 else if (!strcmp(args[1], "external-check")) {
4458 /* excute an external command to check servers' health */
4459 free(curproxy->check_req);
4460 curproxy->check_req = NULL;
4461 curproxy->options2 &= ~PR_O2_CHK_ANY;
4462 curproxy->options2 |= PR_O2_EXT_CHK;
4463 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004464 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004465 int cur_arg;
4466
4467 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4468 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004469 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004470
Willy Tarreau87cf5142011-08-19 22:57:24 +02004471 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004472
4473 free(curproxy->fwdfor_hdr_name);
4474 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4475 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4476
4477 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4478 cur_arg = 2;
4479 while (*(args[cur_arg])) {
4480 if (!strcmp(args[cur_arg], "except")) {
4481 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004482 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004483 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] 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;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004487 }
4488 /* flush useless bits */
4489 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004490 cur_arg += 2;
4491 } else if (!strcmp(args[cur_arg], "header")) {
4492 /* suboption header - needs additional argument for it */
4493 if (*(args[cur_arg+1]) == 0) {
4494 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4495 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004496 err_code |= ERR_ALERT | ERR_FATAL;
4497 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004498 }
4499 free(curproxy->fwdfor_hdr_name);
4500 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4501 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4502 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004503 } else if (!strcmp(args[cur_arg], "if-none")) {
4504 curproxy->options &= ~PR_O_FF_ALWAYS;
4505 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004506 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004507 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004508 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004509 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004510 err_code |= ERR_ALERT | ERR_FATAL;
4511 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004512 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004513 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004514 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004515 else if (!strcmp(args[1], "originalto")) {
4516 int cur_arg;
4517
4518 /* insert x-original-to field, but not for the IP address listed as an except.
4519 * set default options (ie: bitfield, header name, etc)
4520 */
4521
4522 curproxy->options |= PR_O_ORGTO;
4523
4524 free(curproxy->orgto_hdr_name);
4525 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4526 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4527
Willy Tarreau87cf5142011-08-19 22:57:24 +02004528 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004529 cur_arg = 2;
4530 while (*(args[cur_arg])) {
4531 if (!strcmp(args[cur_arg], "except")) {
4532 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004533 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 +02004534 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] 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 /* flush useless bits */
4540 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4541 cur_arg += 2;
4542 } else if (!strcmp(args[cur_arg], "header")) {
4543 /* suboption header - needs additional argument for it */
4544 if (*(args[cur_arg+1]) == 0) {
4545 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4546 file, linenum, args[0], args[1], args[cur_arg]);
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 free(curproxy->orgto_hdr_name);
4551 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4552 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4553 cur_arg += 2;
4554 } else {
4555 /* unknown suboption - catchall */
4556 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4557 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004558 err_code |= ERR_ALERT | ERR_FATAL;
4559 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004560 }
4561 } /* end while loop */
4562 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004563 else {
4564 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004565 err_code |= ERR_ALERT | ERR_FATAL;
4566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004567 }
Willy Tarreau93893792009-07-23 13:19:11 +02004568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004569 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004570 else if (!strcmp(args[0], "default_backend")) {
4571 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004572 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004573
4574 if (*(args[1]) == 0) {
4575 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004576 err_code |= ERR_ALERT | ERR_FATAL;
4577 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004578 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004579 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004580 curproxy->defbe.name = strdup(args[1]);
4581 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004582 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004583 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004584 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004585
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004586 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4587 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 +01004588 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004589 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004590 /* enable reconnections to dispatch */
4591 curproxy->options |= PR_O_REDISP;
4592 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004593 else if (!strcmp(args[0], "http-check")) {
4594 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004595 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004596
4597 if (strcmp(args[1], "disable-on-404") == 0) {
4598 /* enable a graceful server shutdown on an HTTP 404 response */
4599 curproxy->options |= PR_O_DISABLE404;
4600 }
Willy Tarreauef781042010-01-27 11:53:01 +01004601 else if (strcmp(args[1], "send-state") == 0) {
4602 /* enable emission of the apparent state of a server in HTTP checks */
4603 curproxy->options2 |= PR_O2_CHK_SNDST;
4604 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004605 else if (strcmp(args[1], "expect") == 0) {
4606 const char *ptr_arg;
4607 int cur_arg;
4608
4609 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4610 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4611 err_code |= ERR_ALERT | ERR_FATAL;
4612 goto out;
4613 }
4614
4615 cur_arg = 2;
4616 /* consider exclamation marks, sole or at the beginning of a word */
4617 while (*(ptr_arg = args[cur_arg])) {
4618 while (*ptr_arg == '!') {
4619 curproxy->options2 ^= PR_O2_EXP_INV;
4620 ptr_arg++;
4621 }
4622 if (*ptr_arg)
4623 break;
4624 cur_arg++;
4625 }
4626 /* now ptr_arg points to the beginning of a word past any possible
4627 * exclamation mark, and cur_arg is the argument which holds this word.
4628 */
4629 if (strcmp(ptr_arg, "status") == 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_STS;
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, "string") == 0) {
4641 if (!*(args[cur_arg + 1])) {
4642 Alert("parsing [%s:%d] : '%s %s %s' expects <string> 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_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004648 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004649 curproxy->expect_str = strdup(args[cur_arg + 1]);
4650 }
4651 else if (strcmp(ptr_arg, "rstatus") == 0) {
4652 if (!*(args[cur_arg + 1])) {
4653 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4654 file, linenum, args[0], args[1], ptr_arg);
4655 err_code |= ERR_ALERT | ERR_FATAL;
4656 goto out;
4657 }
4658 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004659 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004660 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004661 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004662 free(curproxy->expect_regex);
4663 curproxy->expect_regex = NULL;
4664 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004665 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004666 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4667 error = NULL;
4668 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4669 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4670 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4671 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004672 err_code |= ERR_ALERT | ERR_FATAL;
4673 goto out;
4674 }
4675 }
4676 else if (strcmp(ptr_arg, "rstring") == 0) {
4677 if (!*(args[cur_arg + 1])) {
4678 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4679 file, linenum, args[0], args[1], ptr_arg);
4680 err_code |= ERR_ALERT | ERR_FATAL;
4681 goto out;
4682 }
4683 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004684 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004685 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004686 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004687 free(curproxy->expect_regex);
4688 curproxy->expect_regex = NULL;
4689 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004690 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004691 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4692 error = NULL;
4693 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4694 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4695 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4696 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004697 err_code |= ERR_ALERT | ERR_FATAL;
4698 goto out;
4699 }
4700 }
4701 else {
4702 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4703 file, linenum, args[0], args[1], ptr_arg);
4704 err_code |= ERR_ALERT | ERR_FATAL;
4705 goto out;
4706 }
4707 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004708 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004709 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 +02004710 err_code |= ERR_ALERT | ERR_FATAL;
4711 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004712 }
4713 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004714 else if (!strcmp(args[0], "tcp-check")) {
4715 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4716 err_code |= ERR_WARN;
4717
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004718 if (strcmp(args[1], "comment") == 0) {
4719 int cur_arg;
4720 struct tcpcheck_rule *tcpcheck;
4721
4722 cur_arg = 1;
4723 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4724 tcpcheck->action = TCPCHK_ACT_COMMENT;
4725
4726 if (!*args[cur_arg + 1]) {
4727 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4728 file, linenum, args[cur_arg]);
4729 err_code |= ERR_ALERT | ERR_FATAL;
4730 goto out;
4731 }
4732
4733 tcpcheck->comment = strdup(args[cur_arg + 1]);
4734
4735 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4736 }
4737 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004738 const char *ptr_arg;
4739 int cur_arg;
4740 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004741
4742 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02004743 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
4744 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
4745 tcpcheck->action == TCPCHK_ACT_COMMENT) {
4746 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
4747 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004748
Willy Tarreau5581c272015-05-13 12:24:53 +02004749 if (&tcpcheck->list != &curproxy->tcpcheck_rules
4750 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4751 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4752 file, linenum);
4753 err_code |= ERR_ALERT | ERR_FATAL;
4754 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004755 }
4756
4757 cur_arg = 2;
4758 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4759 tcpcheck->action = TCPCHK_ACT_CONNECT;
4760
4761 /* parsing each parameters to fill up the rule */
4762 while (*(ptr_arg = args[cur_arg])) {
4763 /* tcp port */
4764 if (strcmp(args[cur_arg], "port") == 0) {
4765 if ( (atol(args[cur_arg + 1]) > 65535) ||
4766 (atol(args[cur_arg + 1]) < 1) ){
4767 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4768 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4769 err_code |= ERR_ALERT | ERR_FATAL;
4770 goto out;
4771 }
4772 tcpcheck->port = atol(args[cur_arg + 1]);
4773 cur_arg += 2;
4774 }
4775 /* send proxy protocol */
4776 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4777 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4778 cur_arg++;
4779 }
4780#ifdef USE_OPENSSL
4781 else if (strcmp(args[cur_arg], "ssl") == 0) {
4782 curproxy->options |= PR_O_TCPCHK_SSL;
4783 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4784 cur_arg++;
4785 }
4786#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004787 /* comment for this tcpcheck line */
4788 else if (strcmp(args[cur_arg], "comment") == 0) {
4789 if (!*args[cur_arg + 1]) {
4790 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4791 file, linenum, args[cur_arg]);
4792 err_code |= ERR_ALERT | ERR_FATAL;
4793 goto out;
4794 }
4795 tcpcheck->comment = strdup(args[cur_arg + 1]);
4796 cur_arg += 2;
4797 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004798 else {
4799#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004800 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 +01004801#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004802 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 +01004803#endif /* USE_OPENSSL */
4804 file, linenum, args[0], args[1], args[cur_arg]);
4805 err_code |= ERR_ALERT | ERR_FATAL;
4806 goto out;
4807 }
4808
4809 }
4810
4811 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4812 }
4813 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004814 if (! *(args[2]) ) {
4815 /* SEND string expected */
4816 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4817 file, linenum, args[0], args[1], args[2]);
4818 err_code |= ERR_ALERT | ERR_FATAL;
4819 goto out;
4820 } else {
4821 struct tcpcheck_rule *tcpcheck;
4822
4823 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4824
4825 tcpcheck->action = TCPCHK_ACT_SEND;
4826 tcpcheck->string_len = strlen(args[2]);
4827 tcpcheck->string = strdup(args[2]);
4828 tcpcheck->expect_regex = NULL;
4829
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004830 /* comment for this tcpcheck line */
4831 if (strcmp(args[3], "comment") == 0) {
4832 if (!*args[4]) {
4833 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4834 file, linenum, args[3]);
4835 err_code |= ERR_ALERT | ERR_FATAL;
4836 goto out;
4837 }
4838 tcpcheck->comment = strdup(args[4]);
4839 }
4840
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004841 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4842 }
4843 }
4844 else if (strcmp(args[1], "send-binary") == 0) {
4845 if (! *(args[2]) ) {
4846 /* SEND binary string expected */
4847 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4848 file, linenum, args[0], args[1], args[2]);
4849 err_code |= ERR_ALERT | ERR_FATAL;
4850 goto out;
4851 } else {
4852 struct tcpcheck_rule *tcpcheck;
4853 char *err = NULL;
4854
4855 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4856
4857 tcpcheck->action = TCPCHK_ACT_SEND;
4858 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4859 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4860 file, linenum, args[0], args[1], args[2], err);
4861 err_code |= ERR_ALERT | ERR_FATAL;
4862 goto out;
4863 }
4864 tcpcheck->expect_regex = NULL;
4865
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004866 /* comment for this tcpcheck line */
4867 if (strcmp(args[3], "comment") == 0) {
4868 if (!*args[4]) {
4869 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4870 file, linenum, args[3]);
4871 err_code |= ERR_ALERT | ERR_FATAL;
4872 goto out;
4873 }
4874 tcpcheck->comment = strdup(args[4]);
4875 }
4876
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004877 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4878 }
4879 }
4880 else if (strcmp(args[1], "expect") == 0) {
4881 const char *ptr_arg;
4882 int cur_arg;
4883 int inverse = 0;
4884
4885 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4886 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4887 err_code |= ERR_ALERT | ERR_FATAL;
4888 goto out;
4889 }
4890
4891 cur_arg = 2;
4892 /* consider exclamation marks, sole or at the beginning of a word */
4893 while (*(ptr_arg = args[cur_arg])) {
4894 while (*ptr_arg == '!') {
4895 inverse = !inverse;
4896 ptr_arg++;
4897 }
4898 if (*ptr_arg)
4899 break;
4900 cur_arg++;
4901 }
4902 /* now ptr_arg points to the beginning of a word past any possible
4903 * exclamation mark, and cur_arg is the argument which holds this word.
4904 */
4905 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004906 struct tcpcheck_rule *tcpcheck;
4907 char *err = NULL;
4908
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004909 if (!*(args[cur_arg + 1])) {
4910 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4911 file, linenum, args[0], args[1], ptr_arg);
4912 err_code |= ERR_ALERT | ERR_FATAL;
4913 goto out;
4914 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004915
4916 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4917
4918 tcpcheck->action = TCPCHK_ACT_EXPECT;
4919 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4920 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4921 file, linenum, args[0], args[1], args[2], err);
4922 err_code |= ERR_ALERT | ERR_FATAL;
4923 goto out;
4924 }
4925 tcpcheck->expect_regex = NULL;
4926 tcpcheck->inverse = inverse;
4927
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004928 /* tcpcheck comment */
4929 cur_arg += 2;
4930 if (strcmp(args[cur_arg], "comment") == 0) {
4931 if (!*args[cur_arg + 1]) {
4932 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4933 file, linenum, args[cur_arg + 1]);
4934 err_code |= ERR_ALERT | ERR_FATAL;
4935 goto out;
4936 }
4937 tcpcheck->comment = strdup(args[cur_arg + 1]);
4938 }
4939
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004940 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4941 }
4942 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004943 struct tcpcheck_rule *tcpcheck;
4944
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004945 if (!*(args[cur_arg + 1])) {
4946 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4947 file, linenum, args[0], args[1], ptr_arg);
4948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
4950 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004951
4952 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4953
4954 tcpcheck->action = TCPCHK_ACT_EXPECT;
4955 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4956 tcpcheck->string = strdup(args[cur_arg + 1]);
4957 tcpcheck->expect_regex = NULL;
4958 tcpcheck->inverse = inverse;
4959
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004960 /* tcpcheck comment */
4961 cur_arg += 2;
4962 if (strcmp(args[cur_arg], "comment") == 0) {
4963 if (!*args[cur_arg + 1]) {
4964 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4965 file, linenum, args[cur_arg + 1]);
4966 err_code |= ERR_ALERT | ERR_FATAL;
4967 goto out;
4968 }
4969 tcpcheck->comment = strdup(args[cur_arg + 1]);
4970 }
4971
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004972 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4973 }
4974 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004975 struct tcpcheck_rule *tcpcheck;
4976
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004977 if (!*(args[cur_arg + 1])) {
4978 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4979 file, linenum, args[0], args[1], ptr_arg);
4980 err_code |= ERR_ALERT | ERR_FATAL;
4981 goto out;
4982 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004983
4984 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4985
4986 tcpcheck->action = TCPCHK_ACT_EXPECT;
4987 tcpcheck->string_len = 0;
4988 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004989 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4990 error = NULL;
4991 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4992 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4993 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4994 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004995 err_code |= ERR_ALERT | ERR_FATAL;
4996 goto out;
4997 }
4998 tcpcheck->inverse = inverse;
4999
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005000 /* tcpcheck comment */
5001 cur_arg += 2;
5002 if (strcmp(args[cur_arg], "comment") == 0) {
5003 if (!*args[cur_arg + 1]) {
5004 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5005 file, linenum, args[cur_arg + 1]);
5006 err_code |= ERR_ALERT | ERR_FATAL;
5007 goto out;
5008 }
5009 tcpcheck->comment = strdup(args[cur_arg + 1]);
5010 }
5011
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005012 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5013 }
5014 else {
5015 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5016 file, linenum, args[0], args[1], ptr_arg);
5017 err_code |= ERR_ALERT | ERR_FATAL;
5018 goto out;
5019 }
5020 }
5021 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005022 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005023 err_code |= ERR_ALERT | ERR_FATAL;
5024 goto out;
5025 }
5026 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005027 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005028 if (curproxy == &defproxy) {
5029 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005030 err_code |= ERR_ALERT | ERR_FATAL;
5031 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005032 }
5033
Willy Tarreaub80c2302007-11-30 20:51:32 +01005034 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005035 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005036
5037 if (strcmp(args[1], "fail") == 0) {
5038 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005039 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005040 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5041 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005042 err_code |= ERR_ALERT | ERR_FATAL;
5043 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005044 }
5045
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005046 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5047 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5048 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005049 err_code |= ERR_ALERT | ERR_FATAL;
5050 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005051 }
5052 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5053 }
5054 else {
5055 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005056 err_code |= ERR_ALERT | ERR_FATAL;
5057 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005058 }
5059 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005060#ifdef TPROXY
5061 else if (!strcmp(args[0], "transparent")) {
5062 /* enable transparent proxy connections */
5063 curproxy->options |= PR_O_TRANSP;
5064 }
5065#endif
5066 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005067 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005068 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005069
Willy Tarreaubaaee002006-06-26 02:48:02 +02005070 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 Tarreaubaaee002006-06-26 02:48:02 +02005074 }
5075 curproxy->maxconn = atol(args[1]);
5076 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005077 else if (!strcmp(args[0], "backlog")) { /* backlog */
5078 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005079 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005080
5081 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 Tarreauc73ce2b2008-01-06 10:55:10 +01005085 }
5086 curproxy->backlog = atol(args[1]);
5087 }
Willy Tarreau86034312006-12-29 00:10:33 +01005088 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005089 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005090 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005091
Willy Tarreau86034312006-12-29 00:10:33 +01005092 if (*(args[1]) == 0) {
5093 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005094 err_code |= ERR_ALERT | ERR_FATAL;
5095 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005096 }
5097 curproxy->fullconn = atol(args[1]);
5098 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005099 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5100 if (*(args[1]) == 0) {
5101 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005102 err_code |= ERR_ALERT | ERR_FATAL;
5103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005104 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005105 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5106 if (err) {
5107 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5108 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005109 err_code |= ERR_ALERT | ERR_FATAL;
5110 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005111 }
5112 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005113 }
5114 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005115 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005116 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005117 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005118
Willy Tarreaubaaee002006-06-26 02:48:02 +02005119 if (curproxy == &defproxy) {
5120 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005121 err_code |= ERR_ALERT | ERR_FATAL;
5122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005123 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005124 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005125 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005126
Willy Tarreau902636f2013-03-10 19:44:48 +01005127 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005128 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005129 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005130 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005131 goto out;
5132 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005133
5134 proto = protocol_by_family(sk->ss_family);
5135 if (!proto || !proto->connect) {
5136 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5137 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005138 err_code |= ERR_ALERT | ERR_FATAL;
5139 goto out;
5140 }
5141
5142 if (port1 != port2) {
5143 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5144 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005145 err_code |= ERR_ALERT | ERR_FATAL;
5146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005148
5149 if (!port1) {
5150 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5151 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005152 err_code |= ERR_ALERT | ERR_FATAL;
5153 goto out;
5154 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005155
Willy Tarreaud5191e72010-02-09 20:50:45 +01005156 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005157 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005158 }
5159 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005160 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005161 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005162
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005163 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5164 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005165 err_code |= ERR_ALERT | ERR_FATAL;
5166 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005167 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005168 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005169 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005170 /**
5171 * The syntax for hash-type config element is
5172 * hash-type {map-based|consistent} [[<algo>] avalanche]
5173 *
5174 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5175 */
5176 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005177
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005178 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5179 err_code |= ERR_WARN;
5180
5181 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005182 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5183 }
5184 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005185 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5186 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005187 else if (strcmp(args[1], "avalanche") == 0) {
5188 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]);
5189 err_code |= ERR_ALERT | ERR_FATAL;
5190 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005191 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005192 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005193 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005194 err_code |= ERR_ALERT | ERR_FATAL;
5195 goto out;
5196 }
Bhaskar98634f02013-10-29 23:30:51 -04005197
5198 /* set the hash function to use */
5199 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005200 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005201 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005202
5203 /* if consistent with no argument, then avalanche modifier is also applied */
5204 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5205 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005206 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005207 /* set the hash function */
5208 if (!strcmp(args[2], "sdbm")) {
5209 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5210 }
5211 else if (!strcmp(args[2], "djb2")) {
5212 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005213 }
5214 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005215 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005216 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005217 else if (!strcmp(args[2], "crc32")) {
5218 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5219 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005220 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005221 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 -05005222 err_code |= ERR_ALERT | ERR_FATAL;
5223 goto out;
5224 }
5225
5226 /* set the hash modifier */
5227 if (!strcmp(args[3], "avalanche")) {
5228 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5229 }
5230 else if (*args[3]) {
5231 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5232 err_code |= ERR_ALERT | ERR_FATAL;
5233 goto out;
5234 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005235 }
William Lallemanda73203e2012-03-12 12:48:57 +01005236 }
William Lallemanda73203e2012-03-12 12:48:57 +01005237 else if (strcmp(args[0], "unique-id-format") == 0) {
5238 if (!*(args[1])) {
5239 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5240 err_code |= ERR_ALERT | ERR_FATAL;
5241 goto out;
5242 }
William Lallemand3203ff42012-11-11 17:30:56 +01005243 if (*(args[2])) {
5244 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5245 err_code |= ERR_ALERT | ERR_FATAL;
5246 goto out;
5247 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005248 free(curproxy->conf.uniqueid_format_string);
5249 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005250
Willy Tarreau62a61232013-04-12 18:13:46 +02005251 free(curproxy->conf.uif_file);
5252 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5253 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005254 }
William Lallemanda73203e2012-03-12 12:48:57 +01005255
5256 else if (strcmp(args[0], "unique-id-header") == 0) {
5257 if (!*(args[1])) {
5258 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5259 err_code |= ERR_ALERT | ERR_FATAL;
5260 goto out;
5261 }
5262 free(curproxy->header_unique_id);
5263 curproxy->header_unique_id = strdup(args[1]);
5264 }
5265
William Lallemand723b73a2012-02-08 16:37:49 +01005266 else if (strcmp(args[0], "log-format") == 0) {
5267 if (!*(args[1])) {
5268 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5269 err_code |= ERR_ALERT | ERR_FATAL;
5270 goto out;
5271 }
William Lallemand3203ff42012-11-11 17:30:56 +01005272 if (*(args[2])) {
5273 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5274 err_code |= ERR_ALERT | ERR_FATAL;
5275 goto out;
5276 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005277
Willy Tarreau62a61232013-04-12 18:13:46 +02005278 if (curproxy->conf.logformat_string != default_http_log_format &&
5279 curproxy->conf.logformat_string != default_tcp_log_format &&
5280 curproxy->conf.logformat_string != clf_http_log_format)
5281 free(curproxy->conf.logformat_string);
5282 curproxy->conf.logformat_string = strdup(args[1]);
5283
5284 free(curproxy->conf.lfs_file);
5285 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5286 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005287
5288 /* get a chance to improve log-format error reporting by
5289 * reporting the correct line-number when possible.
5290 */
5291 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5292 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5293 file, linenum, curproxy->id);
5294 err_code |= ERR_WARN;
5295 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005297 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5298 if (*(args[1]) == 0) {
5299 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5300 err_code |= ERR_ALERT | ERR_FATAL;
5301 goto out;
5302 }
5303 free(curproxy->log_tag);
5304 curproxy->log_tag = strdup(args[1]);
5305 }
William Lallemand0f99e342011-10-12 17:50:54 +02005306 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5307 /* delete previous herited or defined syslog servers */
5308 struct logsrv *back;
5309
5310 if (*(args[1]) != 0) {
5311 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5312 err_code |= ERR_ALERT | ERR_FATAL;
5313 goto out;
5314 }
5315
William Lallemand723b73a2012-02-08 16:37:49 +01005316 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5317 LIST_DEL(&tmplogsrv->list);
5318 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005319 }
5320 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005322 struct logsrv *logsrv;
5323
Willy Tarreaubaaee002006-06-26 02:48:02 +02005324 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005325 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005326 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005327 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005328 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005329 LIST_INIT(&node->list);
5330 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5331 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005332 }
5333 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005334 struct sockaddr_storage *sk;
5335 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005336 int arg = 0;
5337 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005338
5339 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005340
Willy Tarreau18324f52014-06-27 18:10:07 +02005341 /* just after the address, a length may be specified */
5342 if (strcmp(args[arg+2], "len") == 0) {
5343 len = atoi(args[arg+3]);
5344 if (len < 80 || len > 65535) {
5345 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5346 file, linenum, args[arg+3]);
5347 err_code |= ERR_ALERT | ERR_FATAL;
5348 goto out;
5349 }
5350 logsrv->maxlen = len;
5351
5352 /* skip these two args */
5353 arg += 2;
5354 }
5355 else
5356 logsrv->maxlen = MAX_SYSLOG_LEN;
5357
5358 if (logsrv->maxlen > global.max_syslog_len) {
5359 global.max_syslog_len = logsrv->maxlen;
5360 logline = realloc(logline, global.max_syslog_len + 1);
5361 }
5362
5363 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005364 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005365 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005366 err_code |= ERR_ALERT | ERR_FATAL;
5367 goto out;
5368
Willy Tarreaubaaee002006-06-26 02:48:02 +02005369 }
5370
William Lallemand0f99e342011-10-12 17:50:54 +02005371 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005372 if (*(args[arg+3])) {
5373 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005374 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005375 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005376 err_code |= ERR_ALERT | ERR_FATAL;
5377 goto out;
5378
Willy Tarreaubaaee002006-06-26 02:48:02 +02005379 }
5380 }
5381
William Lallemand0f99e342011-10-12 17:50:54 +02005382 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005383 if (*(args[arg+4])) {
5384 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005385 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005386 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005387 err_code |= ERR_ALERT | ERR_FATAL;
5388 goto out;
5389
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005390 }
5391 }
5392
Willy Tarreau902636f2013-03-10 19:44:48 +01005393 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005394 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005395 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005396 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005397 goto out;
5398 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005399
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005400 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005401
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005402 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005403 if (port1 != port2) {
5404 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5405 file, linenum, args[0], args[1]);
5406 err_code |= ERR_ALERT | ERR_FATAL;
5407 goto out;
5408 }
5409
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005410 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005411 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005412 }
William Lallemand0f99e342011-10-12 17:50:54 +02005413
5414 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005415 }
5416 else {
5417 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5418 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005419 err_code |= ERR_ALERT | ERR_FATAL;
5420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005421 }
5422 }
5423 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005424 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005425 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005426 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005427 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005428
Willy Tarreau977b8e42006-12-29 14:19:17 +01005429 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005430 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005431
Willy Tarreaubaaee002006-06-26 02:48:02 +02005432 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005433 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5434 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005435 err_code |= ERR_ALERT | ERR_FATAL;
5436 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005437 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005438
5439 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005440 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5441 free(curproxy->conn_src.iface_name);
5442 curproxy->conn_src.iface_name = NULL;
5443 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005444
Willy Tarreau902636f2013-03-10 19:44:48 +01005445 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005446 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005447 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005448 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005449 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005450 goto out;
5451 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005452
5453 proto = protocol_by_family(sk->ss_family);
5454 if (!proto || !proto->connect) {
5455 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005456 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005457 err_code |= ERR_ALERT | ERR_FATAL;
5458 goto out;
5459 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005460
5461 if (port1 != port2) {
5462 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5463 file, linenum, args[0], args[1]);
5464 err_code |= ERR_ALERT | ERR_FATAL;
5465 goto out;
5466 }
5467
Willy Tarreauef9a3602012-12-08 22:29:20 +01005468 curproxy->conn_src.source_addr = *sk;
5469 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005470
5471 cur_arg = 2;
5472 while (*(args[cur_arg])) {
5473 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005474#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5475#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005476 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005477 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5478 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005479 err_code |= ERR_ALERT | ERR_FATAL;
5480 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005481 }
5482#endif
5483 if (!*args[cur_arg + 1]) {
5484 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5485 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005486 err_code |= ERR_ALERT | ERR_FATAL;
5487 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005488 }
5489
5490 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005491 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5492 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005493 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005494 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5495 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005496 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5497 char *name, *end;
5498
5499 name = args[cur_arg+1] + 7;
5500 while (isspace(*name))
5501 name++;
5502
5503 end = name;
5504 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5505 end++;
5506
Willy Tarreauef9a3602012-12-08 22:29:20 +01005507 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5508 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5509 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5510 curproxy->conn_src.bind_hdr_len = end - name;
5511 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5512 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5513 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005514
5515 /* now look for an occurrence number */
5516 while (isspace(*end))
5517 end++;
5518 if (*end == ',') {
5519 end++;
5520 name = end;
5521 if (*end == '-')
5522 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005523 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005524 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005525 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005526 }
5527
Willy Tarreauef9a3602012-12-08 22:29:20 +01005528 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005529 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5530 " occurrences values smaller than %d.\n",
5531 file, linenum, MAX_HDR_HISTORY);
5532 err_code |= ERR_ALERT | ERR_FATAL;
5533 goto out;
5534 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005535 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005536 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005537
Willy Tarreau902636f2013-03-10 19:44:48 +01005538 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005539 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005540 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005541 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005542 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005543 goto out;
5544 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005545
5546 proto = protocol_by_family(sk->ss_family);
5547 if (!proto || !proto->connect) {
5548 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5549 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005550 err_code |= ERR_ALERT | ERR_FATAL;
5551 goto out;
5552 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005553
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005554 if (port1 != port2) {
5555 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5556 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005557 err_code |= ERR_ALERT | ERR_FATAL;
5558 goto out;
5559 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005560 curproxy->conn_src.tproxy_addr = *sk;
5561 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005562 }
5563 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005564#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005565 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005566#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005567#else /* no TPROXY support */
5568 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005569 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005570 err_code |= ERR_ALERT | ERR_FATAL;
5571 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005572#endif
5573 cur_arg += 2;
5574 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005575 }
5576
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005577 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5578#ifdef SO_BINDTODEVICE
5579 if (!*args[cur_arg + 1]) {
5580 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5581 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005582 err_code |= ERR_ALERT | ERR_FATAL;
5583 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005584 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005585 free(curproxy->conn_src.iface_name);
5586 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5587 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005588 global.last_checks |= LSTCHK_NETADM;
5589#else
5590 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5591 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005592 err_code |= ERR_ALERT | ERR_FATAL;
5593 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005594#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005595 cur_arg += 2;
5596 continue;
5597 }
5598 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005599 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005600 err_code |= ERR_ALERT | ERR_FATAL;
5601 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005603 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005604 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5605 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5606 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005607 err_code |= ERR_ALERT | ERR_FATAL;
5608 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005610 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005611 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005612 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5613 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005614 err_code |= ERR_ALERT | ERR_FATAL;
5615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005616 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005617
5618 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005619 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005620 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005621 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005623 }
5624 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005625 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005626 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005627 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005628 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005630 }
5631 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005632 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005633 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005634 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005635 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005636 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005637 }
5638 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005639 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005640 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005641 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005642 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005644 }
5645 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005646 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005647 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005648 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005649 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005651 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005652 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005653 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005654 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005655 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005656 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005657 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005658 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005659 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005660 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005661 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005662 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005663 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005664 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005665
5666 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5667 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 +01005668 }
5669 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005670 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005671 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005672 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005673 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005674 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005675
5676 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5677 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 +01005678 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005679 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005680 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005681 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5682 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005683 err_code |= ERR_ALERT | ERR_FATAL;
5684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005685 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005686
5687 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005688 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005689 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005690 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005692 }
5693 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005694 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005695 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005696 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005697 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005699 }
5700 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005701 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005702 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005703 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005704 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005705 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005706 }
5707 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005708 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005709 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005710 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005711 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005712 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005713 }
5714 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005715 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005716 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005717 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005718 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005719 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005721 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005722 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005723 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005724 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005725 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005726 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005727 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005728 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005729 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005730
Willy Tarreaubaaee002006-06-26 02:48:02 +02005731 if (curproxy == &defproxy) {
5732 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005733 err_code |= ERR_ALERT | ERR_FATAL;
5734 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005735 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005736 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005737 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738
Willy Tarreaubaaee002006-06-26 02:48:02 +02005739 if (*(args[1]) == 0) {
5740 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005741 err_code |= ERR_ALERT | ERR_FATAL;
5742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005743 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005744
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005745 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005746 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5747 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5748 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005749 err_code |= ERR_ALERT | ERR_FATAL;
5750 goto out;
5751 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005752 err_code |= warnif_cond_conflicts(cond,
5753 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5754 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005755 }
5756 else if (*args[2]) {
5757 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5758 file, linenum, args[0], args[2]);
5759 err_code |= ERR_ALERT | ERR_FATAL;
5760 goto out;
5761 }
5762
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005763 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005764 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005765 wl->s = strdup(args[1]);
5766 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005767 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005768 }
5769 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005770 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5772 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005773 err_code |= ERR_ALERT | ERR_FATAL;
5774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005775 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005776
Willy Tarreauade5ec42010-01-28 19:33:49 +01005777 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005778 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005779 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005780 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005782 }
5783 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005784 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005785 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005786 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005787 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005789 }
5790 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005791 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005792 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005793 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005794 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005796 }
5797 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005798 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005799 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5800 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005801 err_code |= ERR_ALERT | ERR_FATAL;
5802 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005803 }
5804
Willy Tarreauade5ec42010-01-28 19:33:49 +01005805 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005806 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005807 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005808 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005810 }
5811 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005812 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005813 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005814 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005815 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005817 }
5818 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005819 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005820 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005821 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005822 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005824 }
5825 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005826 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005827
Willy Tarreaubaaee002006-06-26 02:48:02 +02005828 if (curproxy == &defproxy) {
5829 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005830 err_code |= ERR_ALERT | ERR_FATAL;
5831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005832 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005833 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005834 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005835
Willy Tarreaubaaee002006-06-26 02:48:02 +02005836 if (*(args[1]) == 0) {
5837 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005838 err_code |= ERR_ALERT | ERR_FATAL;
5839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005840 }
5841
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005842 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005843 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5844 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5845 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005846 err_code |= ERR_ALERT | ERR_FATAL;
5847 goto out;
5848 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005849 err_code |= warnif_cond_conflicts(cond,
5850 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5851 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005852 }
5853 else if (*args[2]) {
5854 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5855 file, linenum, args[0], args[2]);
5856 err_code |= ERR_ALERT | ERR_FATAL;
5857 goto out;
5858 }
5859
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005860 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005861 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005862 wl->s = strdup(args[1]);
5863 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005864 }
5865 else if (!strcmp(args[0], "errorloc") ||
5866 !strcmp(args[0], "errorloc302") ||
5867 !strcmp(args[0], "errorloc303")) { /* error location */
5868 int errnum, errlen;
5869 char *err;
5870
Willy Tarreau977b8e42006-12-29 14:19:17 +01005871 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005872 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005873
Willy Tarreaubaaee002006-06-26 02:48:02 +02005874 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005875 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005876 err_code |= ERR_ALERT | ERR_FATAL;
5877 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005878 }
5879
5880 errnum = atol(args[1]);
5881 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005882 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5883 err = malloc(errlen);
5884 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005885 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005886 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5887 err = malloc(errlen);
5888 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005889 }
5890
Willy Tarreau0f772532006-12-23 20:51:41 +01005891 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5892 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005893 chunk_destroy(&curproxy->errmsg[rc]);
5894 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005895 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005896 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005897 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005898
5899 if (rc >= HTTP_ERR_SIZE) {
5900 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5901 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005902 free(err);
5903 }
5904 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005905 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5906 int errnum, errlen, fd;
5907 char *err;
5908 struct stat stat;
5909
5910 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005911 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005912
5913 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005914 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005915 err_code |= ERR_ALERT | ERR_FATAL;
5916 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005917 }
5918
5919 fd = open(args[2], O_RDONLY);
5920 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5921 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5922 file, linenum, args[2], args[1]);
5923 if (fd >= 0)
5924 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005925 err_code |= ERR_ALERT | ERR_FATAL;
5926 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005927 }
5928
Willy Tarreau27a674e2009-08-17 07:23:33 +02005929 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005930 errlen = stat.st_size;
5931 } else {
5932 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005933 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005934 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005935 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005936 }
5937
5938 err = malloc(errlen); /* malloc() must succeed during parsing */
5939 errnum = read(fd, err, errlen);
5940 if (errnum != errlen) {
5941 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5942 file, linenum, args[2], args[1]);
5943 close(fd);
5944 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005945 err_code |= ERR_ALERT | ERR_FATAL;
5946 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005947 }
5948 close(fd);
5949
5950 errnum = atol(args[1]);
5951 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5952 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005953 chunk_destroy(&curproxy->errmsg[rc]);
5954 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005955 break;
5956 }
5957 }
5958
5959 if (rc >= HTTP_ERR_SIZE) {
5960 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5961 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005962 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005963 free(err);
5964 }
5965 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005966 else if (!strcmp(args[0], "compression")) {
5967 struct comp *comp;
5968 if (curproxy->comp == NULL) {
5969 comp = calloc(1, sizeof(struct comp));
5970 curproxy->comp = comp;
5971 } else {
5972 comp = curproxy->comp;
5973 }
5974
5975 if (!strcmp(args[1], "algo")) {
5976 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005977 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005978
William Lallemand82fe75c2012-10-23 10:25:10 +02005979 cur_arg = 2;
5980 if (!*args[cur_arg]) {
5981 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5982 file, linenum, args[0]);
5983 err_code |= ERR_ALERT | ERR_FATAL;
5984 goto out;
5985 }
5986 while (*(args[cur_arg])) {
5987 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5988 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5989 file, linenum, args[0], args[cur_arg]);
5990 err_code |= ERR_ALERT | ERR_FATAL;
5991 goto out;
5992 }
William Lallemand552df672012-11-07 13:21:47 +01005993 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5994 curproxy->comp->algos->end(&ctx);
5995 } else {
5996 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5997 file, linenum, args[0], args[cur_arg]);
5998 err_code |= ERR_ALERT | ERR_FATAL;
5999 goto out;
6000 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006001 cur_arg ++;
6002 continue;
6003 }
6004 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006005 else if (!strcmp(args[1], "offload")) {
6006 comp->offload = 1;
6007 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006008 else if (!strcmp(args[1], "type")) {
6009 int cur_arg;
6010 cur_arg = 2;
6011 if (!*args[cur_arg]) {
6012 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6013 file, linenum, args[0]);
6014 err_code |= ERR_ALERT | ERR_FATAL;
6015 goto out;
6016 }
6017 while (*(args[cur_arg])) {
6018 comp_append_type(comp, args[cur_arg]);
6019 cur_arg ++;
6020 continue;
6021 }
6022 }
6023 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006024 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006025 file, linenum, args[0]);
6026 err_code |= ERR_ALERT | ERR_FATAL;
6027 goto out;
6028 }
6029 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006030 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006031 struct cfg_kw_list *kwl;
6032 int index;
6033
6034 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6035 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6036 if (kwl->kw[index].section != CFG_LISTEN)
6037 continue;
6038 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6039 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006040 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006041 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006042 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006043 err_code |= ERR_ALERT | ERR_FATAL;
6044 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006045 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006046 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006047 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006048 err_code |= ERR_WARN;
6049 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006050 }
Willy Tarreau93893792009-07-23 13:19:11 +02006051 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006052 }
6053 }
6054 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006055
Willy Tarreau6daf3432008-01-22 16:44:08 +01006056 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006057 err_code |= ERR_ALERT | ERR_FATAL;
6058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006059 }
Willy Tarreau93893792009-07-23 13:19:11 +02006060 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006061 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006062 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006063}
6064
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006065int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006066cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6067{
6068#ifdef CONFIG_HAP_NS
6069 const char *err;
6070 const char *item = args[0];
6071
6072 if (!strcmp(item, "namespace_list")) {
6073 return 0;
6074 }
6075 else if (!strcmp(item, "namespace")) {
6076 size_t idx = 1;
6077 const char *current;
6078 while (*(current = args[idx++])) {
6079 err = invalid_char(current);
6080 if (err) {
6081 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6082 file, linenum, *err, item, current);
6083 return ERR_ALERT | ERR_FATAL;
6084 }
6085
6086 if (netns_store_lookup(current, strlen(current))) {
6087 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6088 file, linenum, current);
6089 return ERR_ALERT | ERR_FATAL;
6090 }
6091 if (!netns_store_insert(current)) {
6092 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6093 file, linenum, current);
6094 return ERR_ALERT | ERR_FATAL;
6095 }
6096 }
6097 }
6098
6099 return 0;
6100#else
6101 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6102 file, linenum);
6103 return ERR_ALERT | ERR_FATAL;
6104#endif
6105}
6106
6107int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006108cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6109{
6110
6111 int err_code = 0;
6112 const char *err;
6113
6114 if (!strcmp(args[0], "userlist")) { /* new userlist */
6115 struct userlist *newul;
6116
6117 if (!*args[1]) {
6118 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6119 file, linenum, args[0]);
6120 err_code |= ERR_ALERT | ERR_FATAL;
6121 goto out;
6122 }
6123
6124 err = invalid_char(args[1]);
6125 if (err) {
6126 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6127 file, linenum, *err, args[0], args[1]);
6128 err_code |= ERR_ALERT | ERR_FATAL;
6129 goto out;
6130 }
6131
6132 for (newul = userlist; newul; newul = newul->next)
6133 if (!strcmp(newul->name, args[1])) {
6134 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6135 file, linenum, args[1]);
6136 err_code |= ERR_WARN;
6137 goto out;
6138 }
6139
6140 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6141 if (!newul) {
6142 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6143 err_code |= ERR_ALERT | ERR_ABORT;
6144 goto out;
6145 }
6146
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006147 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006148 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006149 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6150 err_code |= ERR_ALERT | ERR_ABORT;
6151 goto out;
6152 }
6153
6154 newul->next = userlist;
6155 userlist = newul;
6156
6157 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006158 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006159 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006160 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006161
6162 if (!*args[1]) {
6163 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6164 file, linenum, args[0]);
6165 err_code |= ERR_ALERT | ERR_FATAL;
6166 goto out;
6167 }
6168
6169 err = invalid_char(args[1]);
6170 if (err) {
6171 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6172 file, linenum, *err, args[0], args[1]);
6173 err_code |= ERR_ALERT | ERR_FATAL;
6174 goto out;
6175 }
6176
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006177 for (ag = userlist->groups; ag; ag = ag->next)
6178 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006179 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6180 file, linenum, args[1], userlist->name);
6181 err_code |= ERR_ALERT;
6182 goto out;
6183 }
6184
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006185 ag = calloc(1, sizeof(*ag));
6186 if (!ag) {
6187 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6188 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006189 goto out;
6190 }
6191
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006192 ag->name = strdup(args[1]);
6193 if (!ag) {
6194 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6195 err_code |= ERR_ALERT | ERR_ABORT;
6196 goto out;
6197 }
6198
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006199 cur_arg = 2;
6200
6201 while (*args[cur_arg]) {
6202 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006203 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006204 cur_arg += 2;
6205 continue;
6206 } else {
6207 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6208 file, linenum, args[0]);
6209 err_code |= ERR_ALERT | ERR_FATAL;
6210 goto out;
6211 }
6212 }
6213
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006214 ag->next = userlist->groups;
6215 userlist->groups = ag;
6216
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006217 } else if (!strcmp(args[0], "user")) { /* new user */
6218 struct auth_users *newuser;
6219 int cur_arg;
6220
6221 if (!*args[1]) {
6222 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6223 file, linenum, args[0]);
6224 err_code |= ERR_ALERT | ERR_FATAL;
6225 goto out;
6226 }
6227
6228 for (newuser = userlist->users; newuser; newuser = newuser->next)
6229 if (!strcmp(newuser->user, args[1])) {
6230 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6231 file, linenum, args[1], userlist->name);
6232 err_code |= ERR_ALERT;
6233 goto out;
6234 }
6235
6236 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6237 if (!newuser) {
6238 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6239 err_code |= ERR_ALERT | ERR_ABORT;
6240 goto out;
6241 }
6242
6243 newuser->user = strdup(args[1]);
6244
6245 newuser->next = userlist->users;
6246 userlist->users = newuser;
6247
6248 cur_arg = 2;
6249
6250 while (*args[cur_arg]) {
6251 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006252#ifdef CONFIG_HAP_CRYPT
6253 if (!crypt("", args[cur_arg + 1])) {
6254 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6255 file, linenum, newuser->user);
6256 err_code |= ERR_ALERT | ERR_FATAL;
6257 goto out;
6258 }
6259#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006260 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6261 file, linenum);
6262 err_code |= ERR_ALERT;
6263#endif
6264 newuser->pass = strdup(args[cur_arg + 1]);
6265 cur_arg += 2;
6266 continue;
6267 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6268 newuser->pass = strdup(args[cur_arg + 1]);
6269 newuser->flags |= AU_O_INSECURE;
6270 cur_arg += 2;
6271 continue;
6272 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006273 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006274 cur_arg += 2;
6275 continue;
6276 } else {
6277 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6278 file, linenum, args[0]);
6279 err_code |= ERR_ALERT | ERR_FATAL;
6280 goto out;
6281 }
6282 }
6283 } else {
6284 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6285 err_code |= ERR_ALERT | ERR_FATAL;
6286 }
6287
6288out:
6289 return err_code;
6290}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006291
6292/*
6293 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006294 * Returns the error code, 0 if OK, or any combination of :
6295 * - ERR_ABORT: must abort ASAP
6296 * - ERR_FATAL: we can continue parsing but not start the service
6297 * - ERR_WARN: a warning has been emitted
6298 * - ERR_ALERT: an alert has been emitted
6299 * Only the two first ones can stop processing, the two others are just
6300 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006301 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006302int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006303{
William Lallemand64e84512015-05-12 14:25:37 +02006304 char *thisline;
6305 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006306 FILE *f;
6307 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006308 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006309 struct cfg_section *cs = NULL;
6310 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006311 int readbytes = 0;
6312
6313 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006314 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006315 return -1;
6316 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006317
6318 /* Register internal sections */
6319 if (!cfg_register_section("listen", cfg_parse_listen) ||
6320 !cfg_register_section("frontend", cfg_parse_listen) ||
6321 !cfg_register_section("backend", cfg_parse_listen) ||
6322 !cfg_register_section("ruleset", cfg_parse_listen) ||
6323 !cfg_register_section("defaults", cfg_parse_listen) ||
6324 !cfg_register_section("global", cfg_parse_global) ||
6325 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006326 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006327 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006328 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006329 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006330
Willy Tarreaubaaee002006-06-26 02:48:02 +02006331 if ((f=fopen(file,"r")) == NULL)
6332 return -1;
6333
William Lallemandb2f07452015-05-12 14:27:13 +02006334next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006335 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006336 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006337 char *end;
6338 char *args[MAX_LINE_ARGS + 1];
6339 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006340 int dquote = 0; /* double quote */
6341 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006342
Willy Tarreaubaaee002006-06-26 02:48:02 +02006343 linenum++;
6344
6345 end = line + strlen(line);
6346
William Lallemand64e84512015-05-12 14:25:37 +02006347 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006348 /* Check if we reached the limit and the last char is not \n.
6349 * Watch out for the last line without the terminating '\n'!
6350 */
William Lallemand64e84512015-05-12 14:25:37 +02006351 char *newline;
6352 int newlinesize = linesize * 2;
6353
6354 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6355 if (newline == NULL) {
6356 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6357 file, linenum);
6358 err_code |= ERR_ALERT | ERR_FATAL;
6359 continue;
6360 }
6361
6362 readbytes = linesize - 1;
6363 linesize = newlinesize;
6364 thisline = newline;
6365 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006366 }
6367
William Lallemand64e84512015-05-12 14:25:37 +02006368 readbytes = 0;
6369
Willy Tarreaubaaee002006-06-26 02:48:02 +02006370 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006371 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006372 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006373
Willy Tarreaubaaee002006-06-26 02:48:02 +02006374 arg = 0;
6375 args[arg] = line;
6376
6377 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006378 if (*line == '"' && !squote) { /* double quote outside single quotes */
6379 if (dquote)
6380 dquote = 0;
6381 else
6382 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006383 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006384 end--;
6385 }
6386 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6387 if (squote)
6388 squote = 0;
6389 else
6390 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006391 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006392 end--;
6393 }
6394 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006395 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6396 * C equivalent value. Other combinations left unchanged (eg: \1).
6397 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006398 int skip = 0;
6399 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6400 *line = line[1];
6401 skip = 1;
6402 }
6403 else if (line[1] == 'r') {
6404 *line = '\r';
6405 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006406 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006407 else if (line[1] == 'n') {
6408 *line = '\n';
6409 skip = 1;
6410 }
6411 else if (line[1] == 't') {
6412 *line = '\t';
6413 skip = 1;
6414 }
6415 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006416 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006417 unsigned char hex1, hex2;
6418 hex1 = toupper(line[2]) - '0';
6419 hex2 = toupper(line[3]) - '0';
6420 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6421 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6422 *line = (hex1<<4) + hex2;
6423 skip = 3;
6424 }
6425 else {
6426 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006427 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006428 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006429 } else if (line[1] == '"') {
6430 *line = '"';
6431 skip = 1;
6432 } else if (line[1] == '\'') {
6433 *line = '\'';
6434 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006435 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6436 *line = '$';
6437 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006438 }
6439 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006440 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006441 end -= skip;
6442 }
6443 line++;
6444 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006445 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006446 /* end of string, end of loop */
6447 *line = 0;
6448 break;
6449 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006450 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006451 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006452 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006453 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006454 line++;
6455 args[++arg] = line;
6456 }
William Lallemandb2f07452015-05-12 14:27:13 +02006457 else if (dquote && *line == '$') {
6458 /* environment variables are evaluated inside double quotes */
6459 char *var_beg;
6460 char *var_end;
6461 char save_char;
6462 char *value;
6463 int val_len;
6464 int newlinesize;
6465 int braces = 0;
6466
6467 var_beg = line + 1;
6468 var_end = var_beg;
6469
6470 if (*var_beg == '{') {
6471 var_beg++;
6472 var_end++;
6473 braces = 1;
6474 }
6475
6476 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6477 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6478 err_code |= ERR_ALERT | ERR_FATAL;
6479 goto next_line; /* skip current line */
6480 }
6481
6482 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6483 var_end++;
6484
6485 save_char = *var_end;
6486 *var_end = '\0';
6487 value = getenv(var_beg);
6488 *var_end = save_char;
6489 val_len = value ? strlen(value) : 0;
6490
6491 if (braces) {
6492 if (*var_end == '}') {
6493 var_end++;
6494 braces = 0;
6495 } else {
6496 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
6497 err_code |= ERR_ALERT | ERR_FATAL;
6498 goto next_line; /* skip current line */
6499 }
6500 }
6501
6502 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
6503
6504 /* if not enough space in thisline */
6505 if (newlinesize > linesize) {
6506 char *newline;
6507
6508 newline = realloc(thisline, newlinesize * sizeof(*thisline));
6509 if (newline == NULL) {
6510 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
6511 err_code |= ERR_ALERT | ERR_FATAL;
6512 goto next_line; /* slip current line */
6513 }
6514 /* recompute pointers if realloc returns a new pointer */
6515 if (newline != thisline) {
6516 int i;
6517 int diff;
6518
6519 for (i = 0; i <= arg; i++) {
6520 diff = args[i] - thisline;
6521 args[i] = newline + diff;
6522 }
6523
6524 diff = var_end - thisline;
6525 var_end = newline + diff;
6526 diff = end - thisline;
6527 end = newline + diff;
6528 diff = line - thisline;
6529 line = newline + diff;
6530 thisline = newline;
6531 }
6532 linesize = newlinesize;
6533 }
6534
6535 /* insert value inside the line */
6536 memmove(line + val_len, var_end, end - var_end + 1);
6537 memcpy(line, value, val_len);
6538 end += val_len - (var_end - line);
6539 line += val_len;
6540 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006541 else {
6542 line++;
6543 }
6544 }
William Lallemandb2f07452015-05-12 14:27:13 +02006545
William Lallemandf9873ba2015-05-05 17:37:14 +02006546 if (dquote) {
6547 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
6548 err_code |= ERR_ALERT | ERR_FATAL;
6549 }
6550
6551 if (squote) {
6552 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
6553 err_code |= ERR_ALERT | ERR_FATAL;
6554 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006555
6556 /* empty line */
6557 if (!**args)
6558 continue;
6559
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006560 if (*line) {
6561 /* we had to stop due to too many args.
6562 * Let's terminate the string, print the offending part then cut the
6563 * last arg.
6564 */
6565 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6566 line++;
6567 *line = '\0';
6568
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006569 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006570 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006571 err_code |= ERR_ALERT | ERR_FATAL;
6572 args[arg] = line;
6573 }
6574
Willy Tarreau540abe42007-05-02 20:50:16 +02006575 /* zero out remaining args and ensure that at least one entry
6576 * is zeroed out.
6577 */
6578 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006579 args[arg] = line;
6580 }
6581
Willy Tarreau3842f002009-06-14 11:39:52 +02006582 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006583 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006584 char *tmp;
6585
Willy Tarreau3842f002009-06-14 11:39:52 +02006586 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006587 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006588 for (arg=0; *args[arg+1]; arg++)
6589 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006590 *tmp = '\0'; // fix the next arg to \0
6591 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006592 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006593 else if (!strcmp(args[0], "default")) {
6594 kwm = KWM_DEF;
6595 for (arg=0; *args[arg+1]; arg++)
6596 args[arg] = args[arg+1]; // shift args after inversion
6597 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006598
William Lallemand0f99e342011-10-12 17:50:54 +02006599 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6600 strcmp(args[0], "log") != 0) {
6601 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006602 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006603 }
6604
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006605 /* detect section start */
6606 list_for_each_entry(ics, &sections, list) {
6607 if (strcmp(args[0], ics->section_name) == 0) {
6608 cursection = ics->section_name;
6609 cs = ics;
6610 break;
6611 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006612 }
6613
Willy Tarreaubaaee002006-06-26 02:48:02 +02006614 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006615 if (cs)
6616 err_code |= cs->section_parser(file, linenum, args, kwm);
6617 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006618 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006619 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006620 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006621
6622 if (err_code & ERR_ABORT)
6623 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006624 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006625 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02006626 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006627 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006628 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006629}
6630
Willy Tarreau64ab6072014-09-16 12:17:36 +02006631/* This function propagates processes from frontend <from> to backend <to> so
6632 * that it is always guaranteed that a backend pointed to by a frontend is
6633 * bound to all of its processes. After that, if the target is a "listen"
6634 * instance, the function recursively descends the target's own targets along
6635 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6636 * checked first to ensure that <to> is already bound to all processes of
6637 * <from>, there is no risk of looping and we ensure to follow the shortest
6638 * path to the destination.
6639 *
6640 * It is possible to set <to> to NULL for the first call so that the function
6641 * takes care of visiting the initial frontend in <from>.
6642 *
6643 * It is important to note that the function relies on the fact that all names
6644 * have already been resolved.
6645 */
6646void propagate_processes(struct proxy *from, struct proxy *to)
6647{
6648 struct switching_rule *rule;
6649 struct hdr_exp *exp;
6650
6651 if (to) {
6652 /* check whether we need to go down */
6653 if (from->bind_proc &&
6654 (from->bind_proc & to->bind_proc) == from->bind_proc)
6655 return;
6656
6657 if (!from->bind_proc && !to->bind_proc)
6658 return;
6659
6660 to->bind_proc = from->bind_proc ?
6661 (to->bind_proc | from->bind_proc) : 0;
6662
6663 /* now propagate down */
6664 from = to;
6665 }
6666
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006667 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006668 return;
6669
Willy Tarreauf6b70012014-12-18 14:00:43 +01006670 if (from->state == PR_STSTOPPED)
6671 return;
6672
Willy Tarreau64ab6072014-09-16 12:17:36 +02006673 /* default_backend */
6674 if (from->defbe.be)
6675 propagate_processes(from, from->defbe.be);
6676
6677 /* use_backend */
6678 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006679 if (rule->dynamic)
6680 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006681 to = rule->be.backend;
6682 propagate_processes(from, to);
6683 }
6684
6685 /* reqsetbe */
6686 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6687 if (exp->action != ACT_SETBE)
6688 continue;
6689 to = (struct proxy *)exp->replace;
6690 propagate_processes(from, to);
6691 }
6692}
6693
Willy Tarreaubb925012009-07-23 13:36:36 +02006694/*
6695 * Returns the error code, 0 if OK, or any combination of :
6696 * - ERR_ABORT: must abort ASAP
6697 * - ERR_FATAL: we can continue parsing but not start the service
6698 * - ERR_WARN: a warning has been emitted
6699 * - ERR_ALERT: an alert has been emitted
6700 * Only the two first ones can stop processing, the two others are just
6701 * indicators.
6702 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006703int check_config_validity()
6704{
6705 int cfgerr = 0;
6706 struct proxy *curproxy = NULL;
6707 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006708 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006709 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006710 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006711
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006712 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006713 /*
6714 * Now, check for the integrity of all that we have collected.
6715 */
6716
6717 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006718 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006719
Willy Tarreau193b8c62012-11-22 00:17:38 +01006720 if (!global.tune.max_http_hdr)
6721 global.tune.max_http_hdr = MAX_HTTP_HDR;
6722
6723 if (!global.tune.cookie_len)
6724 global.tune.cookie_len = CAPTURE_LEN;
6725
6726 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6727
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006728 /* Post initialisation of the users and groups lists. */
6729 err_code = userlist_postinit();
6730 if (err_code != ERR_NONE)
6731 goto out;
6732
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006733 /* first, we will invert the proxy list order */
6734 curproxy = NULL;
6735 while (proxy) {
6736 struct proxy *next;
6737
6738 next = proxy->next;
6739 proxy->next = curproxy;
6740 curproxy = proxy;
6741 if (!next)
6742 break;
6743 proxy = next;
6744 }
6745
Willy Tarreau419ead82014-09-16 13:41:21 +02006746 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006747 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006748 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006749 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006750 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006751 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006752 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006753 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006754
Willy Tarreau050536d2012-10-04 08:47:34 +02006755 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006756 /* proxy ID not set, use automatic numbering with first
6757 * spare entry starting with next_pxid.
6758 */
6759 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6760 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6761 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006762 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006763 next_pxid++;
6764
Willy Tarreau55ea7572007-06-17 19:56:27 +02006765
Willy Tarreaubaaee002006-06-26 02:48:02 +02006766 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006767 /* ensure we don't keep listeners uselessly bound */
6768 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02006769 free((void *)curproxy->table.peers.name);
6770 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006771 continue;
6772 }
6773
Willy Tarreau102df612014-05-07 23:56:38 +02006774 /* Check multi-process mode compatibility for the current proxy */
6775
6776 if (curproxy->bind_proc) {
6777 /* an explicit bind-process was specified, let's check how many
6778 * processes remain.
6779 */
6780 nbproc = popcount(curproxy->bind_proc);
6781
6782 curproxy->bind_proc &= nbits(global.nbproc);
6783 if (!curproxy->bind_proc && nbproc == 1) {
6784 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);
6785 curproxy->bind_proc = 1;
6786 }
6787 else if (!curproxy->bind_proc && nbproc > 1) {
6788 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);
6789 curproxy->bind_proc = 0;
6790 }
6791 }
6792
Willy Tarreau3d209582014-05-09 17:06:11 +02006793 /* check and reduce the bind-proc of each listener */
6794 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6795 unsigned long mask;
6796
6797 if (!bind_conf->bind_proc)
6798 continue;
6799
6800 mask = nbits(global.nbproc);
6801 if (curproxy->bind_proc)
6802 mask &= curproxy->bind_proc;
6803 /* mask cannot be null here thanks to the previous checks */
6804
6805 nbproc = popcount(bind_conf->bind_proc);
6806 bind_conf->bind_proc &= mask;
6807
6808 if (!bind_conf->bind_proc && nbproc == 1) {
6809 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",
6810 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6811 bind_conf->bind_proc = mask & ~(mask - 1);
6812 }
6813 else if (!bind_conf->bind_proc && nbproc > 1) {
6814 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",
6815 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6816 bind_conf->bind_proc = 0;
6817 }
6818 }
6819
Willy Tarreauff01a212009-03-15 13:46:16 +01006820 switch (curproxy->mode) {
6821 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006822 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006823 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006824 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6825 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006826 cfgerr++;
6827 }
6828
6829 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006830 Warning("config : servers will be ignored for %s '%s'.\n",
6831 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006832 break;
6833
6834 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006835 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006836 break;
6837
6838 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006839 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006840 break;
6841 }
6842
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006843 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006844 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006845 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006846 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6847 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006848 cfgerr++;
6849 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006850#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006851 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006852 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6853 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006854 cfgerr++;
6855 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006856#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006857 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006858 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6859 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006860 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006861 }
6862 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006863 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006864 /* If no LB algo is set in a backend, and we're not in
6865 * transparent mode, dispatch mode nor proxy mode, we
6866 * want to use balance roundrobin by default.
6867 */
6868 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6869 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006870 }
6871 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006872
Willy Tarreau1620ec32011-08-06 17:05:02 +02006873 if (curproxy->options & PR_O_DISPATCH)
6874 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6875 else if (curproxy->options & PR_O_HTTP_PROXY)
6876 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6877 else if (curproxy->options & PR_O_TRANSP)
6878 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006879
Willy Tarreau1620ec32011-08-06 17:05:02 +02006880 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6881 if (curproxy->options & PR_O_DISABLE404) {
6882 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6883 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6884 err_code |= ERR_WARN;
6885 curproxy->options &= ~PR_O_DISABLE404;
6886 }
6887 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6888 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6889 "send-state", proxy_type_str(curproxy), curproxy->id);
6890 err_code |= ERR_WARN;
6891 curproxy->options &= ~PR_O2_CHK_SNDST;
6892 }
Willy Tarreauef781042010-01-27 11:53:01 +01006893 }
6894
Simon Horman98637e52014-06-20 12:30:16 +09006895 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6896 if (!global.external_check) {
6897 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6898 curproxy->id, "option external-check");
6899 cfgerr++;
6900 }
6901 if (!curproxy->check_command) {
6902 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6903 curproxy->id, "option external-check");
6904 cfgerr++;
6905 }
6906 }
6907
Simon Horman64e34162015-02-06 11:11:57 +09006908 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006909 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
6910 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09006911 "'email-alert from', 'email-alert level' 'email-alert mailer', "
6912 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006913 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
6914 "to be present).\n",
6915 proxy_type_str(curproxy), curproxy->id);
6916 err_code |= ERR_WARN;
6917 free_email_alert(curproxy);
6918 }
6919 if (!curproxy->email_alert.myhostname)
6920 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09006921 }
6922
Simon Horman98637e52014-06-20 12:30:16 +09006923 if (curproxy->check_command) {
6924 int clear = 0;
6925 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6926 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6927 "external-check command", proxy_type_str(curproxy), curproxy->id);
6928 err_code |= ERR_WARN;
6929 clear = 1;
6930 }
6931 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6932 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6933 curproxy->id, "external-check command");
6934 cfgerr++;
6935 }
6936 if (clear) {
6937 free(curproxy->check_command);
6938 curproxy->check_command = NULL;
6939 }
6940 }
6941
6942 if (curproxy->check_path) {
6943 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6944 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6945 "external-check path", proxy_type_str(curproxy), curproxy->id);
6946 err_code |= ERR_WARN;
6947 free(curproxy->check_path);
6948 curproxy->check_path = NULL;
6949 }
6950 }
6951
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006952 /* if a default backend was specified, let's find it */
6953 if (curproxy->defbe.name) {
6954 struct proxy *target;
6955
Alex Williams96532db2009-11-01 21:27:13 -05006956 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006957 if (!target) {
6958 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6959 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006960 cfgerr++;
6961 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006962 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6963 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006964 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006965 } else {
6966 free(curproxy->defbe.name);
6967 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006968
6969 /* Emit a warning if this proxy also has some servers */
6970 if (curproxy->srv) {
6971 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6972 curproxy->id);
6973 err_code |= ERR_WARN;
6974 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006975 }
6976 }
6977
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006978 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006979 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6980 /* map jump target for ACT_SETBE in req_rep chain */
6981 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006982 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006983 struct proxy *target;
6984
Willy Tarreaua496b602006-12-17 23:15:24 +01006985 if (exp->action != ACT_SETBE)
6986 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006987
Alex Williams96532db2009-11-01 21:27:13 -05006988 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006989 if (!target) {
6990 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6991 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006992 cfgerr++;
6993 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006994 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6995 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006996 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006997 } else {
6998 free((void *)exp->replace);
6999 exp->replace = (const char *)target;
7000 }
7001 }
7002 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007003
7004 /* find the target proxy for 'use_backend' rules */
7005 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007006 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007007 struct logformat_node *node;
7008 char *pxname;
7009
7010 /* Try to parse the string as a log format expression. If the result
7011 * of the parsing is only one entry containing a simple string, then
7012 * it's a standard string corresponding to a static rule, thus the
7013 * parsing is cancelled and be.name is restored to be resolved.
7014 */
7015 pxname = rule->be.name;
7016 LIST_INIT(&rule->be.expr);
7017 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7018 curproxy->conf.args.file, curproxy->conf.args.line);
7019 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7020
7021 if (!LIST_ISEMPTY(&rule->be.expr)) {
7022 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7023 rule->dynamic = 1;
7024 free(pxname);
7025 continue;
7026 }
7027 /* simple string: free the expression and fall back to static rule */
7028 free(node->arg);
7029 free(node);
7030 }
7031
7032 rule->dynamic = 0;
7033 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007034
Alex Williams96532db2009-11-01 21:27:13 -05007035 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007036
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007037 if (!target) {
7038 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7039 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007040 cfgerr++;
7041 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007042 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7043 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007044 cfgerr++;
7045 } else {
7046 free((void *)rule->be.name);
7047 rule->be.backend = target;
7048 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007049 }
7050
Willy Tarreau64ab6072014-09-16 12:17:36 +02007051 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007052 list_for_each_entry(srule, &curproxy->server_rules, list) {
7053 struct server *target = findserver(curproxy, srule->srv.name);
7054
7055 if (!target) {
7056 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7057 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7058 cfgerr++;
7059 continue;
7060 }
7061 free((void *)srule->srv.name);
7062 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007063 }
7064
Emeric Brunb982a3d2010-01-04 15:45:53 +01007065 /* find the target table for 'stick' rules */
7066 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7067 struct proxy *target;
7068
Emeric Brun1d33b292010-01-04 15:47:17 +01007069 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7070 if (mrule->flags & STK_IS_STORE)
7071 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7072
Emeric Brunb982a3d2010-01-04 15:45:53 +01007073 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007074 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007075 else
7076 target = curproxy;
7077
7078 if (!target) {
7079 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7080 curproxy->id, mrule->table.name);
7081 cfgerr++;
7082 }
7083 else if (target->table.size == 0) {
7084 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7085 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7086 cfgerr++;
7087 }
Willy Tarreau12785782012-04-27 21:37:17 +02007088 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7089 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007090 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7091 cfgerr++;
7092 }
7093 else {
7094 free((void *)mrule->table.name);
7095 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007096 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007097 }
7098 }
7099
7100 /* find the target table for 'store response' rules */
7101 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7102 struct proxy *target;
7103
Emeric Brun1d33b292010-01-04 15:47:17 +01007104 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7105
Emeric Brunb982a3d2010-01-04 15:45:53 +01007106 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007107 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007108 else
7109 target = curproxy;
7110
7111 if (!target) {
7112 Alert("Proxy '%s': unable to find store table '%s'.\n",
7113 curproxy->id, mrule->table.name);
7114 cfgerr++;
7115 }
7116 else if (target->table.size == 0) {
7117 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7118 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7119 cfgerr++;
7120 }
Willy Tarreau12785782012-04-27 21:37:17 +02007121 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7122 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007123 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7124 cfgerr++;
7125 }
7126 else {
7127 free((void *)mrule->table.name);
7128 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007129 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007130 }
7131 }
7132
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007133 /* find the target table for 'tcp-request' layer 4 rules */
7134 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7135 struct proxy *target;
7136
Willy Tarreaub4c84932013-07-23 19:15:30 +02007137 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007138 continue;
7139
7140 if (trule->act_prm.trk_ctr.table.n)
7141 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
7142 else
7143 target = curproxy;
7144
7145 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007146 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7147 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007148 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007149 cfgerr++;
7150 }
7151 else if (target->table.size == 0) {
7152 Alert("Proxy '%s': table '%s' used but not configured.\n",
7153 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7154 cfgerr++;
7155 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007156 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7157 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7158 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 +01007159 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007160 cfgerr++;
7161 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007162 else {
7163 free(trule->act_prm.trk_ctr.table.n);
7164 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007165 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007166 * to pass a list of counters to track and allocate them right here using
7167 * stktable_alloc_data_type().
7168 */
7169 }
7170 }
7171
Willy Tarreaud1f96522010-08-03 19:34:32 +02007172 /* find the target table for 'tcp-request' layer 6 rules */
7173 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7174 struct proxy *target;
7175
Willy Tarreaub4c84932013-07-23 19:15:30 +02007176 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007177 continue;
7178
7179 if (trule->act_prm.trk_ctr.table.n)
7180 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
7181 else
7182 target = curproxy;
7183
7184 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007185 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7186 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007187 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007188 cfgerr++;
7189 }
7190 else if (target->table.size == 0) {
7191 Alert("Proxy '%s': table '%s' used but not configured.\n",
7192 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7193 cfgerr++;
7194 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007195 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7196 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7197 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 +01007198 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007199 cfgerr++;
7200 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007201 else {
7202 free(trule->act_prm.trk_ctr.table.n);
7203 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007204 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007205 * to pass a list of counters to track and allocate them right here using
7206 * stktable_alloc_data_type().
7207 */
7208 }
7209 }
7210
Willy Tarreau09448f72014-06-25 18:12:15 +02007211 /* find the target table for 'http-request' layer 7 rules */
7212 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7213 struct proxy *target;
7214
7215 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
7216 continue;
7217
7218 if (hrqrule->act_prm.trk_ctr.table.n)
7219 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
7220 else
7221 target = curproxy;
7222
7223 if (!target) {
7224 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7225 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
7226 http_req_trk_idx(hrqrule->action));
7227 cfgerr++;
7228 }
7229 else if (target->table.size == 0) {
7230 Alert("Proxy '%s': table '%s' used but not configured.\n",
7231 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
7232 cfgerr++;
7233 }
7234 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
7235 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7236 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
7237 http_req_trk_idx(hrqrule->action));
7238 cfgerr++;
7239 }
7240 else {
7241 free(hrqrule->act_prm.trk_ctr.table.n);
7242 hrqrule->act_prm.trk_ctr.table.t = &target->table;
7243 /* Note: if we decide to enhance the track-sc syntax, we may be able
7244 * to pass a list of counters to track and allocate them right here using
7245 * stktable_alloc_data_type().
7246 */
7247 }
7248 }
7249
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007250 /* move any "block" rules at the beginning of the http-request rules */
7251 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7252 /* insert block_rules into http_req_rules at the beginning */
7253 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7254 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7255 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7256 curproxy->http_req_rules.n = curproxy->block_rules.n;
7257 LIST_INIT(&curproxy->block_rules);
7258 }
7259
Emeric Brun32da3c42010-09-23 18:39:19 +02007260 if (curproxy->table.peers.name) {
7261 struct peers *curpeers = peers;
7262
7263 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7264 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7265 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007266 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007267 break;
7268 }
7269 }
7270
7271 if (!curpeers) {
7272 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7273 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007274 free((void *)curproxy->table.peers.name);
7275 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007276 cfgerr++;
7277 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007278 else if (curpeers->state == PR_STSTOPPED) {
7279 /* silently disable this peers section */
7280 curproxy->table.peers.p = NULL;
7281 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007282 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007283 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7284 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007285 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007286 cfgerr++;
7287 }
7288 }
7289
Simon Horman9dc49962015-01-30 11:22:59 +09007290
7291 if (curproxy->email_alert.mailers.name) {
7292 struct mailers *curmailers = mailers;
7293
7294 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7295 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7296 free(curproxy->email_alert.mailers.name);
7297 curproxy->email_alert.mailers.m = curmailers;
7298 curmailers->users++;
7299 break;
7300 }
7301 }
7302
7303 if (!curmailers) {
7304 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7305 curproxy->id, curproxy->email_alert.mailers.name);
7306 free_email_alert(curproxy);
7307 cfgerr++;
7308 }
7309 }
7310
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007311 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007312 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007313 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7314 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7315 "proxy", curproxy->id);
7316 cfgerr++;
7317 goto out_uri_auth_compat;
7318 }
7319
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007320 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007321 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007322 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007323 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007324
Willy Tarreau95fa4692010-02-01 13:05:50 +01007325 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7326 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007327
7328 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007329 uri_auth_compat_req[i++] = "realm";
7330 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7331 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007332
Willy Tarreau95fa4692010-02-01 13:05:50 +01007333 uri_auth_compat_req[i++] = "unless";
7334 uri_auth_compat_req[i++] = "{";
7335 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7336 uri_auth_compat_req[i++] = "}";
7337 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007338
Willy Tarreauff011f22011-01-06 17:51:27 +01007339 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7340 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007341 cfgerr++;
7342 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007343 }
7344
Willy Tarreauff011f22011-01-06 17:51:27 +01007345 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007346
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007347 if (curproxy->uri_auth->auth_realm) {
7348 free(curproxy->uri_auth->auth_realm);
7349 curproxy->uri_auth->auth_realm = NULL;
7350 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007351
7352 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007353 }
7354out_uri_auth_compat:
7355
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007356 /* compile the log format */
7357 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007358 if (curproxy->conf.logformat_string != default_http_log_format &&
7359 curproxy->conf.logformat_string != default_tcp_log_format &&
7360 curproxy->conf.logformat_string != clf_http_log_format)
7361 free(curproxy->conf.logformat_string);
7362 curproxy->conf.logformat_string = NULL;
7363 free(curproxy->conf.lfs_file);
7364 curproxy->conf.lfs_file = NULL;
7365 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007366 }
7367
Willy Tarreau62a61232013-04-12 18:13:46 +02007368 if (curproxy->conf.logformat_string) {
7369 curproxy->conf.args.ctx = ARGC_LOG;
7370 curproxy->conf.args.file = curproxy->conf.lfs_file;
7371 curproxy->conf.args.line = curproxy->conf.lfs_line;
7372 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007373 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_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
Willy Tarreau62a61232013-04-12 18:13:46 +02007378 if (curproxy->conf.uniqueid_format_string) {
7379 curproxy->conf.args.ctx = ARGC_UIF;
7380 curproxy->conf.args.file = curproxy->conf.uif_file;
7381 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007382 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007383 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007384 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007385 curproxy->conf.args.file = NULL;
7386 curproxy->conf.args.line = 0;
7387 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007388
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007389 /* only now we can check if some args remain unresolved.
7390 * This must be done after the users and groups resolution.
7391 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007392 cfgerr += smp_resolve_args(curproxy);
7393 if (!cfgerr)
7394 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007395
Willy Tarreau2738a142006-07-08 17:28:09 +02007396 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007397 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007398 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007399 (!curproxy->timeout.connect ||
7400 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007401 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007402 " | While not properly invalid, you will certainly encounter various problems\n"
7403 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007404 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007405 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007406 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007407 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007408
Willy Tarreau1fa31262007-12-03 00:36:16 +01007409 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7410 * We must still support older configurations, so let's find out whether those
7411 * parameters have been set or must be copied from contimeouts.
7412 */
7413 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007414 if (!curproxy->timeout.tarpit ||
7415 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007416 /* tarpit timeout not set. We search in the following order:
7417 * default.tarpit, curr.connect, default.connect.
7418 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007419 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007420 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007421 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007422 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007423 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007424 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007425 }
7426 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007427 (!curproxy->timeout.queue ||
7428 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007429 /* queue timeout not set. We search in the following order:
7430 * default.queue, curr.connect, default.connect.
7431 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007432 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007433 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007434 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007435 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007436 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007437 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007438 }
7439 }
7440
Willy Tarreau1620ec32011-08-06 17:05:02 +02007441 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007442 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7443 curproxy->check_req = (char *)malloc(curproxy->check_len);
7444 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007445 }
7446
Willy Tarreau215663d2014-06-13 18:30:23 +02007447 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7448 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7449 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7450 proxy_type_str(curproxy), curproxy->id);
7451 err_code |= ERR_WARN;
7452 }
7453
Willy Tarreau193b8c62012-11-22 00:17:38 +01007454 /* ensure that cookie capture length is not too large */
7455 if (curproxy->capture_len >= global.tune.cookie_len) {
7456 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7457 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7458 err_code |= ERR_WARN;
7459 curproxy->capture_len = global.tune.cookie_len - 1;
7460 }
7461
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007462 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007463 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007464 curproxy->req_cap_pool = create_pool("ptrcap",
7465 curproxy->nb_req_cap * sizeof(char *),
7466 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007467 }
7468
7469 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007470 curproxy->rsp_cap_pool = create_pool("ptrcap",
7471 curproxy->nb_rsp_cap * sizeof(char *),
7472 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007473 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007474
Willy Tarreaubaaee002006-06-26 02:48:02 +02007475 /* first, we will invert the servers list order */
7476 newsrv = NULL;
7477 while (curproxy->srv) {
7478 struct server *next;
7479
7480 next = curproxy->srv->next;
7481 curproxy->srv->next = newsrv;
7482 newsrv = curproxy->srv;
7483 if (!next)
7484 break;
7485 curproxy->srv = next;
7486 }
7487
Willy Tarreau17edc812014-01-03 12:14:34 +01007488 /* Check that no server name conflicts. This causes trouble in the stats.
7489 * We only emit a warning for the first conflict affecting each server,
7490 * in order to avoid combinatory explosion if all servers have the same
7491 * name. We do that only for servers which do not have an explicit ID,
7492 * because these IDs were made also for distinguishing them and we don't
7493 * want to annoy people who correctly manage them.
7494 */
7495 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7496 struct server *other_srv;
7497
7498 if (newsrv->puid)
7499 continue;
7500
7501 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7502 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7503 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7504 newsrv->conf.file, newsrv->conf.line,
7505 proxy_type_str(curproxy), curproxy->id,
7506 newsrv->id, other_srv->conf.line);
7507 break;
7508 }
7509 }
7510 }
7511
Willy Tarreaudd701652010-05-25 23:03:02 +02007512 /* assign automatic UIDs to servers which don't have one yet */
7513 next_id = 1;
7514 newsrv = curproxy->srv;
7515 while (newsrv != NULL) {
7516 if (!newsrv->puid) {
7517 /* server ID not set, use automatic numbering with first
7518 * spare entry starting with next_svid.
7519 */
7520 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7521 newsrv->conf.id.key = newsrv->puid = next_id;
7522 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7523 }
7524 next_id++;
7525 newsrv = newsrv->next;
7526 }
7527
Willy Tarreau20697042007-11-15 23:26:18 +01007528 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007529 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007530
Willy Tarreau62c3be22012-01-20 13:12:32 +01007531 /*
7532 * If this server supports a maxconn parameter, it needs a dedicated
7533 * tasks to fill the emptied slots when a connection leaves.
7534 * Also, resolve deferred tracking dependency if needed.
7535 */
7536 newsrv = curproxy->srv;
7537 while (newsrv != NULL) {
7538 if (newsrv->minconn > newsrv->maxconn) {
7539 /* Only 'minconn' was specified, or it was higher than or equal
7540 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7541 * this will avoid further useless expensive computations.
7542 */
7543 newsrv->maxconn = newsrv->minconn;
7544 } else if (newsrv->maxconn && !newsrv->minconn) {
7545 /* minconn was not specified, so we set it to maxconn */
7546 newsrv->minconn = newsrv->maxconn;
7547 }
7548
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007549#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007550 if (newsrv->use_ssl || newsrv->check.use_ssl)
7551 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007552#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007553
Willy Tarreau2f075e92013-12-03 11:11:34 +01007554 /* set the check type on the server */
7555 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7556
Willy Tarreau62c3be22012-01-20 13:12:32 +01007557 if (newsrv->trackit) {
7558 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007559 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007560 char *pname, *sname;
7561
7562 pname = newsrv->trackit;
7563 sname = strrchr(pname, '/');
7564
7565 if (sname)
7566 *sname++ = '\0';
7567 else {
7568 sname = pname;
7569 pname = NULL;
7570 }
7571
7572 if (pname) {
7573 px = findproxy(pname, PR_CAP_BE);
7574 if (!px) {
7575 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7576 proxy_type_str(curproxy), curproxy->id,
7577 newsrv->id, pname);
7578 cfgerr++;
7579 goto next_srv;
7580 }
7581 } else
7582 px = curproxy;
7583
7584 srv = findserver(px, sname);
7585 if (!srv) {
7586 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7587 proxy_type_str(curproxy), curproxy->id,
7588 newsrv->id, sname);
7589 cfgerr++;
7590 goto next_srv;
7591 }
7592
Willy Tarreau32091232014-05-16 13:52:00 +02007593 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7594 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7595 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007596 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007597 "tracking as it does not have any check nor agent enabled.\n",
7598 proxy_type_str(curproxy), curproxy->id,
7599 newsrv->id, px->id, srv->id);
7600 cfgerr++;
7601 goto next_srv;
7602 }
7603
7604 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7605
7606 if (loop) {
7607 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7608 "belongs to a tracking chain looping back to %s/%s.\n",
7609 proxy_type_str(curproxy), curproxy->id,
7610 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007611 cfgerr++;
7612 goto next_srv;
7613 }
7614
7615 if (curproxy != px &&
7616 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7617 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7618 "tracking: disable-on-404 option inconsistency.\n",
7619 proxy_type_str(curproxy), curproxy->id,
7620 newsrv->id, px->id, srv->id);
7621 cfgerr++;
7622 goto next_srv;
7623 }
7624
7625 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007626 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007627 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007628 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007629 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007630 }
7631
7632 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007633 newsrv->tracknext = srv->trackers;
7634 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007635
7636 free(newsrv->trackit);
7637 newsrv->trackit = NULL;
7638 }
7639 next_srv:
7640 newsrv = newsrv->next;
7641 }
7642
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007643 /* We have to initialize the server lookup mechanism depending
7644 * on what LB algorithm was choosen.
7645 */
7646
7647 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7648 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7649 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007650 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7651 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7652 init_server_map(curproxy);
7653 } else {
7654 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7655 fwrr_init_server_groups(curproxy);
7656 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007657 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007658
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007659 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007660 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7661 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7662 fwlc_init_server_tree(curproxy);
7663 } else {
7664 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7665 fas_init_server_tree(curproxy);
7666 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007667 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007668
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007669 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007670 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7671 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7672 chash_init_server_tree(curproxy);
7673 } else {
7674 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7675 init_server_map(curproxy);
7676 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007677 break;
7678 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007679
7680 if (curproxy->options & PR_O_LOGASAP)
7681 curproxy->to_log &= ~LW_BYTES;
7682
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007683 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007684 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007685 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7686 proxy_type_str(curproxy), curproxy->id);
7687 err_code |= ERR_WARN;
7688 }
7689
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007690 if (curproxy->mode != PR_MODE_HTTP) {
7691 int optnum;
7692
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007693 if (curproxy->uri_auth) {
7694 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7695 proxy_type_str(curproxy), curproxy->id);
7696 err_code |= ERR_WARN;
7697 curproxy->uri_auth = NULL;
7698 }
7699
Willy Tarreau87cf5142011-08-19 22:57:24 +02007700 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007701 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7702 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7703 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007704 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007705 }
7706
7707 if (curproxy->options & PR_O_ORGTO) {
7708 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7709 "originalto", proxy_type_str(curproxy), curproxy->id);
7710 err_code |= ERR_WARN;
7711 curproxy->options &= ~PR_O_ORGTO;
7712 }
7713
7714 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7715 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7716 (curproxy->cap & cfg_opts[optnum].cap) &&
7717 (curproxy->options & cfg_opts[optnum].val)) {
7718 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7719 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7720 err_code |= ERR_WARN;
7721 curproxy->options &= ~cfg_opts[optnum].val;
7722 }
7723 }
7724
7725 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7726 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7727 (curproxy->cap & cfg_opts2[optnum].cap) &&
7728 (curproxy->options2 & cfg_opts2[optnum].val)) {
7729 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7730 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7731 err_code |= ERR_WARN;
7732 curproxy->options2 &= ~cfg_opts2[optnum].val;
7733 }
7734 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007735
Pieter Baauwd551fb52013-05-08 22:49:23 +02007736#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007737 if (curproxy->conn_src.bind_hdr_occ) {
7738 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007739 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007740 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007741 err_code |= ERR_WARN;
7742 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007743#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007744 }
7745
Willy Tarreaubaaee002006-06-26 02:48:02 +02007746 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007747 * ensure that we're not cross-dressing a TCP server into HTTP.
7748 */
7749 newsrv = curproxy->srv;
7750 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007751 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007752 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7753 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007754 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007755 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007756
Willy Tarreau0cec3312011-10-31 13:49:26 +01007757 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7758 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7759 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7760 err_code |= ERR_WARN;
7761 }
7762
Willy Tarreauc93cd162014-05-13 15:54:22 +02007763 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007764 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7765 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7766 err_code |= ERR_WARN;
7767 }
7768
Pieter Baauwd551fb52013-05-08 22:49:23 +02007769#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007770 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7771 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007772 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 +01007773 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007774 err_code |= ERR_WARN;
7775 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007776#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007777 newsrv = newsrv->next;
7778 }
7779
Willy Tarreaue42bd962014-09-16 16:21:19 +02007780 /* check if we have a frontend with "tcp-request content" looking at L7
7781 * with no inspect-delay
7782 */
7783 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7784 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7785 if (trule->action == TCP_ACT_CAPTURE &&
7786 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7787 break;
7788 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7789 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7790 break;
7791 }
7792
7793 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7794 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7795 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7796 " This means that these rules will randomly find their contents. This can be fixed by"
7797 " setting the tcp-request inspect-delay.\n",
7798 proxy_type_str(curproxy), curproxy->id);
7799 err_code |= ERR_WARN;
7800 }
7801 }
7802
Willy Tarreauc1a21672009-08-16 22:37:44 +02007803 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007804 if (!curproxy->accept)
7805 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007806
Willy Tarreauc1a21672009-08-16 22:37:44 +02007807 if (curproxy->tcp_req.inspect_delay ||
7808 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007809 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007810
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007811 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007812 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007813 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007814 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007815
7816 /* both TCP and HTTP must check switching rules */
7817 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7818 }
7819
7820 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007821 if (curproxy->tcp_req.inspect_delay ||
7822 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7823 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7824
Emeric Brun97679e72010-09-23 17:56:44 +02007825 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7826 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7827
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007828 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007829 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007830 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007831 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007832
7833 /* If the backend does requires RDP cookie persistence, we have to
7834 * enable the corresponding analyser.
7835 */
7836 if (curproxy->options2 & PR_O2_RDPC_PRST)
7837 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7838 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007839 }
7840
7841 /***********************************************************/
7842 /* At this point, target names have already been resolved. */
7843 /***********************************************************/
7844
7845 /* Check multi-process mode compatibility */
7846
7847 if (global.nbproc > 1 && global.stats_fe) {
7848 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7849 unsigned long mask;
7850
7851 mask = nbits(global.nbproc);
7852 if (global.stats_fe->bind_proc)
7853 mask &= global.stats_fe->bind_proc;
7854
7855 if (bind_conf->bind_proc)
7856 mask &= bind_conf->bind_proc;
7857
7858 /* stop here if more than one process is used */
7859 if (popcount(mask) > 1)
7860 break;
7861 }
7862 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7863 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");
7864 }
7865 }
7866
7867 /* Make each frontend inherit bind-process from its listeners when not specified. */
7868 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7869 if (curproxy->bind_proc)
7870 continue;
7871
7872 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7873 unsigned long mask;
7874
Willy Tarreaue428b082015-05-04 21:57:58 +02007875 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007876 curproxy->bind_proc |= mask;
7877 }
7878
7879 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02007880 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007881 }
7882
7883 if (global.stats_fe) {
7884 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7885 unsigned long mask;
7886
Willy Tarreaue428b082015-05-04 21:57:58 +02007887 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007888 global.stats_fe->bind_proc |= mask;
7889 }
7890 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02007891 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007892 }
7893
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007894 /* propagate bindings from frontends to backends. Don't do it if there
7895 * are any fatal errors as we must not call it with unresolved proxies.
7896 */
7897 if (!cfgerr) {
7898 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7899 if (curproxy->cap & PR_CAP_FE)
7900 propagate_processes(curproxy, NULL);
7901 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007902 }
7903
7904 /* Bind each unbound backend to all processes when not specified. */
7905 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7906 if (curproxy->bind_proc)
7907 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02007908 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007909 }
7910
7911 /*******************************************************/
7912 /* At this step, all proxies have a non-null bind_proc */
7913 /*******************************************************/
7914
7915 /* perform the final checks before creating tasks */
7916
7917 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7918 struct listener *listener;
7919 unsigned int next_id;
7920 int nbproc;
7921
7922 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007923
Emeric Brunc52962f2012-11-15 18:28:02 +01007924#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007925 /* Configure SSL for each bind line.
7926 * Note: if configuration fails at some point, the ->ctx member
7927 * remains NULL so that listeners can later detach.
7928 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007929 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007930 int alloc_ctx;
7931
Emeric Brunc52962f2012-11-15 18:28:02 +01007932 if (!bind_conf->is_ssl) {
7933 if (bind_conf->default_ctx) {
7934 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7935 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7936 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007937 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007938 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007939 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007940 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007941 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007942 cfgerr++;
7943 continue;
7944 }
7945
Emeric Brun8dc60392014-05-09 13:52:00 +02007946 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007947 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007948 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7949 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");
7950 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007951 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007952 cfgerr++;
7953 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007954 }
7955
Emeric Brunfc0421f2012-09-07 17:30:07 +02007956 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007957 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007958 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007959#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007960
Willy Tarreaue6b98942007-10-29 01:09:36 +01007961 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007962 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007963 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007964 if (!listener->luid) {
7965 /* listener ID not set, use automatic numbering with first
7966 * spare entry starting with next_luid.
7967 */
7968 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7969 listener->conf.id.key = listener->luid = next_id;
7970 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007971 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007972 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007973
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007974 /* enable separate counters */
7975 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7976 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007977 if (!listener->name)
7978 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007979 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007980
Willy Tarreaue6b98942007-10-29 01:09:36 +01007981 if (curproxy->options & PR_O_TCP_NOLING)
7982 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007983 if (!listener->maxconn)
7984 listener->maxconn = curproxy->maxconn;
7985 if (!listener->backlog)
7986 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007987 if (!listener->maxaccept)
7988 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7989
7990 /* we want to have an optimal behaviour on single process mode to
7991 * maximize the work at once, but in multi-process we want to keep
7992 * some fairness between processes, so we target half of the max
7993 * number of events to be balanced over all the processes the proxy
7994 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7995 * used to disable the limit.
7996 */
7997 if (listener->maxaccept > 0) {
7998 if (nbproc > 1)
7999 listener->maxaccept = (listener->maxaccept + 1) / 2;
8000 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8001 }
8002
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008003 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008004 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008005 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008006 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008007
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008008 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8009 listener->options |= LI_O_TCP_RULES;
8010
Willy Tarreaude3041d2010-05-31 10:56:17 +02008011 if (curproxy->mon_mask.s_addr)
8012 listener->options |= LI_O_CHK_MONNET;
8013
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008014 /* smart accept mode is automatic in HTTP mode */
8015 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008016 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008017 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8018 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008019 }
8020
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008021 /* Release unused SSL configs */
8022 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8023 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008024 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008025#ifdef USE_OPENSSL
8026 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008027 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008028 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008029 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008030 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008031 if(bind_conf->keys_ref) {
8032 free(bind_conf->keys_ref->filename);
8033 free(bind_conf->keys_ref->tlskeys);
8034 free(bind_conf->keys_ref);
8035 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008036#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008037 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008038
Willy Tarreau102df612014-05-07 23:56:38 +02008039 if (nbproc > 1) {
8040 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008041 int count, maxproc = 0;
8042
8043 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8044 count = popcount(bind_conf->bind_proc);
8045 if (count > maxproc)
8046 maxproc = count;
8047 }
8048 /* backends have 0, frontends have 1 or more */
8049 if (maxproc != 1)
8050 Warning("Proxy '%s': in multi-process mode, stats will be"
8051 " limited to process assigned to the current request.\n",
8052 curproxy->id);
8053
Willy Tarreau102df612014-05-07 23:56:38 +02008054 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8055 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8056 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008057 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008058 }
Willy Tarreau102df612014-05-07 23:56:38 +02008059 if (curproxy->appsession_name) {
8060 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
8061 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008062 }
Willy Tarreau102df612014-05-07 23:56:38 +02008063 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8064 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8065 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008066 }
8067 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008068
8069 /* create the task associated with the proxy */
8070 curproxy->task = task_new();
8071 if (curproxy->task) {
8072 curproxy->task->context = curproxy;
8073 curproxy->task->process = manage_proxy;
8074 /* no need to queue, it will be done automatically if some
8075 * listener gets limited.
8076 */
8077 curproxy->task->expire = TICK_ETERNITY;
8078 } else {
8079 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8080 curproxy->id);
8081 cfgerr++;
8082 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008083 }
8084
Willy Tarreaufbb78422011-06-05 15:38:35 +02008085 /* automatically compute fullconn if not set. We must not do it in the
8086 * loop above because cross-references are not yet fully resolved.
8087 */
8088 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8089 /* If <fullconn> is not set, let's set it to 10% of the sum of
8090 * the possible incoming frontend's maxconns.
8091 */
8092 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8093 struct proxy *fe;
8094 int total = 0;
8095
8096 /* sum up the number of maxconns of frontends which
8097 * reference this backend at least once or which are
8098 * the same one ('listen').
8099 */
8100 for (fe = proxy; fe; fe = fe->next) {
8101 struct switching_rule *rule;
8102 struct hdr_exp *exp;
8103 int found = 0;
8104
8105 if (!(fe->cap & PR_CAP_FE))
8106 continue;
8107
8108 if (fe == curproxy) /* we're on a "listen" instance */
8109 found = 1;
8110
8111 if (fe->defbe.be == curproxy) /* "default_backend" */
8112 found = 1;
8113
8114 /* check if a "use_backend" rule matches */
8115 if (!found) {
8116 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008117 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008118 found = 1;
8119 break;
8120 }
8121 }
8122 }
8123
8124 /* check if a "reqsetbe" rule matches */
8125 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
8126 if (exp->action == ACT_SETBE &&
8127 (struct proxy *)exp->replace == curproxy) {
8128 found = 1;
8129 break;
8130 }
8131 }
8132
8133 /* now we've checked all possible ways to reference a backend
8134 * from a frontend.
8135 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008136 if (!found)
8137 continue;
8138 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008139 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008140 /* we have the sum of the maxconns in <total>. We only
8141 * keep 10% of that sum to set the default fullconn, with
8142 * a hard minimum of 1 (to avoid a divide by zero).
8143 */
8144 curproxy->fullconn = (total + 9) / 10;
8145 if (!curproxy->fullconn)
8146 curproxy->fullconn = 1;
8147 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008148 }
8149
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008150 /*
8151 * Recount currently required checks.
8152 */
8153
8154 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8155 int optnum;
8156
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008157 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8158 if (curproxy->options & cfg_opts[optnum].val)
8159 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008160
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008161 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8162 if (curproxy->options2 & cfg_opts2[optnum].val)
8163 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008164 }
8165
Willy Tarreau0fca4832015-05-01 19:12:05 +02008166 /* compute the required process bindings for the peers */
8167 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8168 if (curproxy->table.peers.p)
8169 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8170
Willy Tarreau122541c2011-09-07 21:24:49 +02008171 if (peers) {
8172 struct peers *curpeers = peers, **last;
8173 struct peer *p, *pb;
8174
Willy Tarreau1e273012015-05-01 19:15:17 +02008175 /* Remove all peers sections which don't have a valid listener,
8176 * which are not used by any table, or which are bound to more
8177 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008178 */
8179 last = &peers;
8180 while (*last) {
8181 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008182
8183 if (curpeers->state == PR_STSTOPPED) {
8184 /* the "disabled" keyword was present */
8185 if (curpeers->peers_fe)
8186 stop_proxy(curpeers->peers_fe);
8187 curpeers->peers_fe = NULL;
8188 }
8189 else if (!curpeers->peers_fe) {
8190 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8191 curpeers->id, localpeer);
8192 }
Willy Tarreau1e273012015-05-01 19:15:17 +02008193 else if (popcount(curpeers->peers_fe->bind_proc) != 1) {
8194 /* either it's totally stopped or too much used */
8195 if (curpeers->peers_fe->bind_proc) {
8196 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008197 "running in different processes (%d different ones). "
8198 "Check global.nbproc and all tables' bind-process "
8199 "settings.\n", curpeers->id, popcount(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008200 cfgerr++;
8201 }
8202 stop_proxy(curpeers->peers_fe);
8203 curpeers->peers_fe = NULL;
8204 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008205 else {
Willy Tarreau122541c2011-09-07 21:24:49 +02008206 last = &curpeers->next;
8207 continue;
8208 }
8209
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008210 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008211 p = curpeers->remote;
8212 while (p) {
8213 pb = p->next;
8214 free(p->id);
8215 free(p);
8216 p = pb;
8217 }
8218
8219 /* Destroy and unlink this curpeers section.
8220 * Note: curpeers is backed up into *last.
8221 */
8222 free(curpeers->id);
8223 curpeers = curpeers->next;
8224 free(*last);
8225 *last = curpeers;
8226 }
8227 }
8228
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008229 /* initialize stick-tables on backend capable proxies. This must not
8230 * be done earlier because the data size may be discovered while parsing
8231 * other proxies.
8232 */
8233 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8234 if (curproxy->state == PR_STSTOPPED)
8235 continue;
8236
8237 if (!stktable_init(&curproxy->table)) {
8238 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8239 cfgerr++;
8240 }
8241 }
8242
Simon Horman0d16a402015-01-30 11:22:58 +09008243 if (mailers) {
8244 struct mailers *curmailers = mailers, **last;
8245 struct mailer *m, *mb;
8246
8247 /* Remove all mailers sections which don't have a valid listener.
8248 * This can happen when a mailers section is never referenced.
8249 */
8250 last = &mailers;
8251 while (*last) {
8252 curmailers = *last;
8253 if (curmailers->users) {
8254 last = &curmailers->next;
8255 continue;
8256 }
8257
8258 Warning("Removing incomplete section 'mailers %s'.\n",
8259 curmailers->id);
8260
8261 m = curmailers->mailer_list;
8262 while (m) {
8263 mb = m->next;
8264 free(m->id);
8265 free(m);
8266 m = mb;
8267 }
8268
8269 /* Destroy and unlink this curmailers section.
8270 * Note: curmailers is backed up into *last.
8271 */
8272 free(curmailers->id);
8273 curmailers = curmailers->next;
8274 free(*last);
8275 *last = curmailers;
8276 }
8277 }
8278
Willy Tarreau34eb6712011-10-24 18:15:04 +02008279 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008280 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008281 MEM_F_SHARED);
8282
Willy Tarreaubb925012009-07-23 13:36:36 +02008283 if (cfgerr > 0)
8284 err_code |= ERR_ALERT | ERR_FATAL;
8285 out:
8286 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008287}
8288
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008289/*
8290 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8291 * parsing sessions.
8292 */
8293void cfg_register_keywords(struct cfg_kw_list *kwl)
8294{
8295 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8296}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008297
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008298/*
8299 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8300 */
8301void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8302{
8303 LIST_DEL(&kwl->list);
8304 LIST_INIT(&kwl->list);
8305}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008306
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008307/* this function register new section in the haproxy configuration file.
8308 * <section_name> is the name of this new section and <section_parser>
8309 * is the called parser. If two section declaration have the same name,
8310 * only the first declared is used.
8311 */
8312int cfg_register_section(char *section_name,
8313 int (*section_parser)(const char *, int, char **, int))
8314{
8315 struct cfg_section *cs;
8316
8317 cs = calloc(1, sizeof(*cs));
8318 if (!cs) {
8319 Alert("register section '%s': out of memory.\n", section_name);
8320 return 0;
8321 }
8322
8323 cs->section_name = section_name;
8324 cs->section_parser = section_parser;
8325
8326 LIST_ADDQ(&sections, &cs->list);
8327
8328 return 1;
8329}
8330
Willy Tarreaubaaee002006-06-26 02:48:02 +02008331/*
8332 * Local variables:
8333 * c-indent-level: 8
8334 * c-basic-offset: 8
8335 * End:
8336 */