blob: 7ffc0377f2540c44e1d7ca4815ef6d3e51c085b6 [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
William Lallemand6e62fb62015-04-28 16:55:23 +0200324/*
325 * Report a fatal Alert when there is too much arguments
326 * The index is the current keyword in args
327 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
328 * Fill err_code with an ERR_ALERT and an ERR_FATAL
329 */
330int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
331{
332 char *kw = NULL;
333 int i;
334
335 if (!*args[index + maxarg + 1])
336 return 0;
337
338 memprintf(&kw, "%s", args[0]);
339 for (i = 1; i <= index; i++) {
340 memprintf(&kw, "%s %s", kw, args[i]);
341 }
342
343 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
344 free(kw);
345 *err_code |= ERR_ALERT | ERR_FATAL;
346 return 1;
347}
348
349/*
350 * same as alertif_too_many_args_idx with a 0 index
351 */
352int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
353{
354 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
355}
356
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200357/* Report a warning if a rule is placed after a 'tcp-request content' rule.
358 * Return 1 if the warning has been emitted, otherwise 0.
359 */
360int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
361{
362 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
363 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
364 file, line, arg);
365 return 1;
366 }
367 return 0;
368}
369
Willy Tarreau61d18892009-03-31 10:49:21 +0200370/* Report a warning if a rule is placed after a 'block' rule.
371 * Return 1 if the warning has been emitted, otherwise 0.
372 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100373int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200374{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200375 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200376 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
377 file, line, arg);
378 return 1;
379 }
380 return 0;
381}
382
Willy Tarreau5002f572014-04-23 01:32:02 +0200383/* Report a warning if a rule is placed after an 'http_request' rule.
384 * Return 1 if the warning has been emitted, otherwise 0.
385 */
386int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
387{
388 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
389 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
390 file, line, arg);
391 return 1;
392 }
393 return 0;
394}
395
Willy Tarreau61d18892009-03-31 10:49:21 +0200396/* Report a warning if a rule is placed after a reqrewrite rule.
397 * Return 1 if the warning has been emitted, otherwise 0.
398 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100399int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200400{
401 if (proxy->req_exp) {
402 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
403 file, line, arg);
404 return 1;
405 }
406 return 0;
407}
408
409/* Report a warning if a rule is placed after a reqadd rule.
410 * Return 1 if the warning has been emitted, otherwise 0.
411 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100414 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200415 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
416 file, line, arg);
417 return 1;
418 }
419 return 0;
420}
421
422/* Report a warning if a rule is placed after a redirect rule.
423 * Return 1 if the warning has been emitted, otherwise 0.
424 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100425int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200426{
427 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
428 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
429 file, line, arg);
430 return 1;
431 }
432 return 0;
433}
434
435/* Report a warning if a rule is placed after a 'use_backend' rule.
436 * Return 1 if the warning has been emitted, otherwise 0.
437 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100438int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200439{
440 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
441 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
442 file, line, arg);
443 return 1;
444 }
445 return 0;
446}
447
Willy Tarreauee445d92014-04-23 01:39:04 +0200448/* Report a warning if a rule is placed after a 'use-server' rule.
449 * Return 1 if the warning has been emitted, otherwise 0.
450 */
451int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
452{
453 if (!LIST_ISEMPTY(&proxy->server_rules)) {
454 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
455 file, line, arg);
456 return 1;
457 }
458 return 0;
459}
460
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200461/* report a warning if a "tcp request connection" rule is dangerously placed */
462int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
463{
464 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
465 warnif_rule_after_block(proxy, file, line, arg) ||
466 warnif_rule_after_http_req(proxy, file, line, arg) ||
467 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) ||
470 warnif_rule_after_use_backend(proxy, file, line, arg) ||
471 warnif_rule_after_use_server(proxy, file, line, arg);
472}
473
474/* report a warning if a "tcp request content" rule is dangerously placed */
475int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
476{
477 return warnif_rule_after_block(proxy, file, line, arg) ||
478 warnif_rule_after_http_req(proxy, file, line, arg) ||
479 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
480 warnif_rule_after_reqadd(proxy, file, line, arg) ||
481 warnif_rule_after_redirect(proxy, file, line, arg) ||
482 warnif_rule_after_use_backend(proxy, file, line, arg) ||
483 warnif_rule_after_use_server(proxy, file, line, arg);
484}
485
Willy Tarreau61d18892009-03-31 10:49:21 +0200486/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100487int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200488{
Willy Tarreau5002f572014-04-23 01:32:02 +0200489 return warnif_rule_after_http_req(proxy, file, line, arg) ||
490 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
491 warnif_rule_after_reqadd(proxy, file, line, arg) ||
492 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200493 warnif_rule_after_use_backend(proxy, file, line, arg) ||
494 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200495}
496
497/* report a warning if an http-request rule is dangerously placed */
498int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
499{
Willy Tarreau61d18892009-03-31 10:49:21 +0200500 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
501 warnif_rule_after_reqadd(proxy, file, line, arg) ||
502 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200503 warnif_rule_after_use_backend(proxy, file, line, arg) ||
504 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200505}
506
507/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100508int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200509{
510 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
511 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200512 warnif_rule_after_use_backend(proxy, file, line, arg) ||
513 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200514}
515
516/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100517int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200518{
519 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200520 warnif_rule_after_use_backend(proxy, file, line, arg) ||
521 warnif_rule_after_use_server(proxy, file, line, arg);
522}
523
524/* report a warning if a redirect rule is dangerously placed */
525int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
526{
527 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
528 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200529}
530
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100531/* Report it if a request ACL condition uses some keywords that are incompatible
532 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
533 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
534 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100535 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100536static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100537{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100538 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200539 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100540
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100541 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100542 return 0;
543
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100544 acl = acl_cond_conflicts(cond, where);
545 if (acl) {
546 if (acl->name && *acl->name)
547 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
548 file, line, acl->name, sample_ckp_names(where));
549 else
550 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 +0200551 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100552 return ERR_WARN;
553 }
554 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100555 return 0;
556
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100557 if (acl->name && *acl->name)
558 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200559 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100560 else
561 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200562 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100563 return ERR_WARN;
564}
565
Willy Tarreaubaaee002006-06-26 02:48:02 +0200566/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200567 * parse a line in a <global> section. Returns the error code, 0 if OK, or
568 * any combination of :
569 * - ERR_ABORT: must abort ASAP
570 * - ERR_FATAL: we can continue parsing but not start the service
571 * - ERR_WARN: a warning has been emitted
572 * - ERR_ALERT: an alert has been emitted
573 * Only the two first ones can stop processing, the two others are just
574 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200576int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577{
Willy Tarreau058e9072009-07-20 09:30:05 +0200578 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200579 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580
581 if (!strcmp(args[0], "global")) { /* new section */
582 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200583 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200586 else if (!strcmp(args[0], "ca-base")) {
587#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200588 if(alertif_too_many_args(1, file, linenum, args, &err_code))
589 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200590 if (global.ca_base != NULL) {
591 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
592 err_code |= ERR_ALERT;
593 goto out;
594 }
595 if (*(args[1]) == 0) {
596 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
597 err_code |= ERR_ALERT | ERR_FATAL;
598 goto out;
599 }
600 global.ca_base = strdup(args[1]);
601#else
602 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT | ERR_FATAL;
604 goto out;
605#endif
606 }
607 else if (!strcmp(args[0], "crt-base")) {
608#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200609 if (alertif_too_many_args(1, file, linenum, args, &err_code))
610 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200611 if (global.crt_base != NULL) {
612 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
613 err_code |= ERR_ALERT;
614 goto out;
615 }
616 if (*(args[1]) == 0) {
617 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
618 err_code |= ERR_ALERT | ERR_FATAL;
619 goto out;
620 }
621 global.crt_base = strdup(args[1]);
622#else
623 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT | ERR_FATAL;
625 goto out;
626#endif
627 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200629 if (alertif_too_many_args(0, file, linenum, args, &err_code))
630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200631 global.mode |= MODE_DAEMON;
632 }
633 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200634 if (alertif_too_many_args(0, file, linenum, args, &err_code))
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 global.mode |= MODE_DEBUG;
637 }
638 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200639 if (alertif_too_many_args(0, file, linenum, args, &err_code))
640 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100641 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200643 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200644 if (alertif_too_many_args(0, file, linenum, args, &err_code))
645 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100646 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200647 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200648 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200649 if (alertif_too_many_args(0, file, linenum, args, &err_code))
650 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100651 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100653 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200654 if (alertif_too_many_args(0, file, linenum, args, &err_code))
655 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100656 global.tune.options &= ~GTUNE_USE_SPLICE;
657 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200658 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200659 if (alertif_too_many_args(0, file, linenum, args, &err_code))
660 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200661 global.tune.options &= ~GTUNE_USE_GAI;
662 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200663 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200664 if (alertif_too_many_args(0, file, linenum, args, &err_code))
665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666 global.mode |= MODE_QUIET;
667 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200668 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200669 if (alertif_too_many_args(1, file, linenum, args, &err_code))
670 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200671 if (global.tune.maxpollevents != 0) {
672 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT;
674 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200675 }
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200680 }
681 global.tune.maxpollevents = atol(args[1]);
682 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100683 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200684 if (alertif_too_many_args(1, file, linenum, args, &err_code))
685 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100686 if (global.tune.maxaccept != 0) {
687 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT;
689 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100690 }
691 if (*(args[1]) == 0) {
692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100695 }
696 global.tune.maxaccept = atol(args[1]);
697 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200698 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200699 if (alertif_too_many_args(1, file, linenum, args, &err_code))
700 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200701 if (*(args[1]) == 0) {
702 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
703 err_code |= ERR_ALERT | ERR_FATAL;
704 goto out;
705 }
706 global.tune.chksize = atol(args[1]);
707 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200708#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200709 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200710 if (alertif_too_many_args(0, file, linenum, args, &err_code))
711 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200712 global.tune.sslprivatecache = 1;
713 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100714 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200715 if (alertif_too_many_args(1, file, linenum, args, &err_code))
716 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200717 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.sslcachesize = atol(args[1]);
723 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100724 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
725 unsigned int ssllifetime;
726 const char *res;
727
William Lallemand1a748ae2015-05-19 16:37:23 +0200728 if (alertif_too_many_args(1, file, linenum, args, &err_code))
729 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100730 if (*(args[1]) == 0) {
731 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
734 }
735
736 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
737 if (res) {
738 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
739 file, linenum, *res, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743
744 global.tune.ssllifetime = ssllifetime;
745 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100746 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200747 if (alertif_too_many_args(1, file, linenum, args, &err_code))
748 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100749 if (*(args[1]) == 0) {
750 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
751 err_code |= ERR_ALERT | ERR_FATAL;
752 goto out;
753 }
754 global.tune.ssl_max_record = atol(args[1]);
755 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200756#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200757 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200758 if (alertif_too_many_args(1, file, linenum, args, &err_code))
759 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200760 if (*(args[1]) == 0) {
761 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764 }
765 global.tune.ssl_default_dh_param = atol(args[1]);
766 if (global.tune.ssl_default_dh_param < 1024) {
767 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
768 err_code |= ERR_ALERT | ERR_FATAL;
769 goto out;
770 }
771 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200772#endif
Remi Gacogne47783ef2015-05-29 15:53:22 +0200773#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100774 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200775 if (alertif_too_many_args(1, file, linenum, args, &err_code))
776 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
781 }
782 global.tune.buf_limit = atol(args[1]);
783 if (global.tune.buf_limit) {
784 if (global.tune.buf_limit < 3)
785 global.tune.buf_limit = 3;
786 if (global.tune.buf_limit <= global.tune.reserved_bufs)
787 global.tune.buf_limit = global.tune.reserved_bufs + 1;
788 }
789 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100790 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200791 if (alertif_too_many_args(1, file, linenum, args, &err_code))
792 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100793 if (*(args[1]) == 0) {
794 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
795 err_code |= ERR_ALERT | ERR_FATAL;
796 goto out;
797 }
798 global.tune.reserved_bufs = atol(args[1]);
799 if (global.tune.reserved_bufs < 2)
800 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100801 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
802 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100803 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200804 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200805 if (alertif_too_many_args(1, file, linenum, args, &err_code))
806 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200807 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.bufsize = atol(args[1]);
813 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
814 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100815 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100816 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200817 }
818 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200819 if (alertif_too_many_args(1, file, linenum, args, &err_code))
820 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200821 if (*(args[1]) == 0) {
822 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
823 err_code |= ERR_ALERT | ERR_FATAL;
824 goto out;
825 }
826 global.tune.maxrewrite = atol(args[1]);
827 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
828 global.tune.maxrewrite = global.tune.bufsize / 2;
829 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100830 else if (!strcmp(args[0], "tune.idletimer")) {
831 unsigned int idle;
832 const char *res;
833
William Lallemand1a748ae2015-05-19 16:37:23 +0200834 if (alertif_too_many_args(1, file, linenum, args, &err_code))
835 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100836 if (*(args[1]) == 0) {
837 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
838 err_code |= ERR_ALERT | ERR_FATAL;
839 goto out;
840 }
841
842 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
843 if (res) {
844 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
845 file, linenum, *res, args[0]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849
850 if (idle > 65535) {
851 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
852 err_code |= ERR_ALERT | ERR_FATAL;
853 goto out;
854 }
855 global.tune.idle_timer = idle;
856 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100857 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200858 if (alertif_too_many_args(1, file, linenum, args, &err_code))
859 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100860 if (global.tune.client_rcvbuf != 0) {
861 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
862 err_code |= ERR_ALERT;
863 goto out;
864 }
865 if (*(args[1]) == 0) {
866 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
867 err_code |= ERR_ALERT | ERR_FATAL;
868 goto out;
869 }
870 global.tune.client_rcvbuf = atol(args[1]);
871 }
872 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200873 if (alertif_too_many_args(1, file, linenum, args, &err_code))
874 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100875 if (global.tune.server_rcvbuf != 0) {
876 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
877 err_code |= ERR_ALERT;
878 goto out;
879 }
880 if (*(args[1]) == 0) {
881 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
884 }
885 global.tune.server_rcvbuf = atol(args[1]);
886 }
887 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200888 if (alertif_too_many_args(1, file, linenum, args, &err_code))
889 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100890 if (global.tune.client_sndbuf != 0) {
891 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
892 err_code |= ERR_ALERT;
893 goto out;
894 }
895 if (*(args[1]) == 0) {
896 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
897 err_code |= ERR_ALERT | ERR_FATAL;
898 goto out;
899 }
900 global.tune.client_sndbuf = atol(args[1]);
901 }
902 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200903 if (alertif_too_many_args(1, file, linenum, args, &err_code))
904 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100905 if (global.tune.server_sndbuf != 0) {
906 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
907 err_code |= ERR_ALERT;
908 goto out;
909 }
910 if (*(args[1]) == 0) {
911 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
912 err_code |= ERR_ALERT | ERR_FATAL;
913 goto out;
914 }
915 global.tune.server_sndbuf = atol(args[1]);
916 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200917 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200918 if (alertif_too_many_args(1, file, linenum, args, &err_code))
919 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200920 if (*(args[1]) == 0) {
921 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
922 err_code |= ERR_ALERT | ERR_FATAL;
923 goto out;
924 }
925 global.tune.pipesize = atol(args[1]);
926 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100927 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200928 if (alertif_too_many_args(1, file, linenum, args, &err_code))
929 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100930 if (*(args[1]) == 0) {
931 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
932 err_code |= ERR_ALERT | ERR_FATAL;
933 goto out;
934 }
935 global.tune.cookie_len = atol(args[1]) + 1;
936 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200937 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200938 if (alertif_too_many_args(1, file, linenum, args, &err_code))
939 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200940 if (*(args[1]) == 0) {
941 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
942 err_code |= ERR_ALERT | ERR_FATAL;
943 goto out;
944 }
945 global.tune.max_http_hdr = atol(args[1]);
946 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100947 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
948#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200949 if (alertif_too_many_args(1, file, linenum, args, &err_code))
950 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100951 if (*args[1]) {
952 global.tune.zlibmemlevel = atoi(args[1]);
953 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
954 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
955 file, linenum, args[0]);
956 err_code |= ERR_ALERT | ERR_FATAL;
957 goto out;
958 }
959 } else {
960 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
961 file, linenum, args[0]);
962 err_code |= ERR_ALERT | ERR_FATAL;
963 goto out;
964 }
965#else
966 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
967 err_code |= ERR_ALERT | ERR_FATAL;
968 goto out;
969#endif
970 }
971 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
972#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200973 if (alertif_too_many_args(1, file, linenum, args, &err_code))
974 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100975 if (*args[1]) {
976 global.tune.zlibwindowsize = atoi(args[1]);
977 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
978 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
979 file, linenum, args[0]);
980 err_code |= ERR_ALERT | ERR_FATAL;
981 goto out;
982 }
983 } else {
984 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
985 file, linenum, args[0]);
986 err_code |= ERR_ALERT | ERR_FATAL;
987 goto out;
988 }
989#else
990 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
993#endif
994 }
William Lallemandf3747832012-11-09 12:33:10 +0100995 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200996 if (alertif_too_many_args(1, file, linenum, args, &err_code))
997 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100998 if (*args[1]) {
999 global.tune.comp_maxlevel = atoi(args[1]);
1000 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1001 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1002 file, linenum, args[0]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005 }
1006 } else {
1007 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1008 file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011 }
1012 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001013 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1014 if (*args[1]) {
1015 global.tune.pattern_cache = atoi(args[1]);
1016 if (global.tune.pattern_cache < 0) {
1017 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1018 file, linenum, args[0]);
1019 err_code |= ERR_ALERT | ERR_FATAL;
1020 goto out;
1021 }
1022 } else {
1023 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1024 file, linenum, args[0]);
1025 err_code |= ERR_ALERT | ERR_FATAL;
1026 goto out;
1027 }
1028 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001029 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001030 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001032 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001033 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001034 err_code |= ERR_ALERT;
1035 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001036 }
1037 if (*(args[1]) == 0) {
1038 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001039 err_code |= ERR_ALERT | ERR_FATAL;
1040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001041 }
1042 global.uid = atol(args[1]);
1043 }
1044 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001045 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001047 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001048 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001049 err_code |= ERR_ALERT;
1050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 }
1052 if (*(args[1]) == 0) {
1053 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001054 err_code |= ERR_ALERT | ERR_FATAL;
1055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 }
1057 global.gid = atol(args[1]);
1058 }
Simon Horman98637e52014-06-20 12:30:16 +09001059 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001060 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1061 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001062 global.external_check = 1;
1063 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001064 /* user/group name handling */
1065 else if (!strcmp(args[0], "user")) {
1066 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001067 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1068 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001069 if (global.uid != 0) {
1070 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001071 err_code |= ERR_ALERT;
1072 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001073 }
1074 errno = 0;
1075 ha_user = getpwnam(args[1]);
1076 if (ha_user != NULL) {
1077 global.uid = (int)ha_user->pw_uid;
1078 }
1079 else {
1080 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 +02001081 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001082 }
1083 }
1084 else if (!strcmp(args[0], "group")) {
1085 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001086 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1087 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001088 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001089 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT;
1091 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001092 }
1093 errno = 0;
1094 ha_group = getgrnam(args[1]);
1095 if (ha_group != NULL) {
1096 global.gid = (int)ha_group->gr_gid;
1097 }
1098 else {
1099 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 +02001100 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001101 }
1102 }
1103 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001104 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001105 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1106 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 if (*(args[1]) == 0) {
1108 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001111 }
1112 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001113 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1114 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1115 file, linenum, args[0], LONGBITS, global.nbproc);
1116 err_code |= ERR_ALERT | ERR_FATAL;
1117 goto out;
1118 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 }
1120 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001121 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001123 if (global.maxconn != 0) {
1124 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001125 err_code |= ERR_ALERT;
1126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001127 }
1128 if (*(args[1]) == 0) {
1129 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001130 err_code |= ERR_ALERT | ERR_FATAL;
1131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001132 }
1133 global.maxconn = atol(args[1]);
1134#ifdef SYSTEM_MAXCONN
1135 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1136 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);
1137 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001138 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001139 }
1140#endif /* SYSTEM_MAXCONN */
1141 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001142 else if (!strcmp(args[0], "maxsslconn")) {
1143#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001144 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1145 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001146 if (*(args[1]) == 0) {
1147 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1148 err_code |= ERR_ALERT | ERR_FATAL;
1149 goto out;
1150 }
1151 global.maxsslconn = atol(args[1]);
1152#else
Emeric Brun0914df82012-10-02 18:45:42 +02001153 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1154 err_code |= ERR_ALERT | ERR_FATAL;
1155 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001156#endif
1157 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001158 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1159#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001160 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1161 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001162 if (*(args[1]) == 0) {
1163 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1164 err_code |= ERR_ALERT | ERR_FATAL;
1165 goto out;
1166 }
1167 free(global.listen_default_ciphers);
1168 global.listen_default_ciphers = strdup(args[1]);
1169#else
1170 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1171 err_code |= ERR_ALERT | ERR_FATAL;
1172 goto out;
1173#endif
1174 }
1175 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1176#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001177 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1178 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001179 if (*(args[1]) == 0) {
1180 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1181 err_code |= ERR_ALERT | ERR_FATAL;
1182 goto out;
1183 }
1184 free(global.connect_default_ciphers);
1185 global.connect_default_ciphers = strdup(args[1]);
1186#else
1187 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1188 err_code |= ERR_ALERT | ERR_FATAL;
1189 goto out;
1190#endif
1191 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001192#ifdef USE_OPENSSL
1193#ifndef OPENSSL_NO_DH
1194 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1195 if (*(args[1]) == 0) {
1196 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1197 err_code |= ERR_ALERT | ERR_FATAL;
1198 goto out;
1199 }
1200 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1201 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1202 err_code |= ERR_ALERT | ERR_FATAL;
1203 goto out;
1204 }
1205 }
1206#endif
1207#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001208 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001209 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1210 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001211 if (*(args[1]) == 0) {
1212 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1213 err_code |= ERR_ALERT | ERR_FATAL;
1214 goto out;
1215 }
1216 if (strcmp(args[1],"none") == 0)
1217 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1218 else if (strcmp(args[1],"required") == 0)
1219 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1220 else {
1221 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto out;
1224 }
1225 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001226 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001227 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1228 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001229 if (global.cps_lim != 0) {
1230 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1231 err_code |= ERR_ALERT;
1232 goto out;
1233 }
1234 if (*(args[1]) == 0) {
1235 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1236 err_code |= ERR_ALERT | ERR_FATAL;
1237 goto out;
1238 }
1239 global.cps_lim = atol(args[1]);
1240 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001241 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001242 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1243 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001244 if (global.sps_lim != 0) {
1245 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1246 err_code |= ERR_ALERT;
1247 goto out;
1248 }
1249 if (*(args[1]) == 0) {
1250 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1251 err_code |= ERR_ALERT | ERR_FATAL;
1252 goto out;
1253 }
1254 global.sps_lim = atol(args[1]);
1255 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001256 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001257 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1258 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001259 if (global.ssl_lim != 0) {
1260 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1261 err_code |= ERR_ALERT;
1262 goto out;
1263 }
1264 if (*(args[1]) == 0) {
1265 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1266 err_code |= ERR_ALERT | ERR_FATAL;
1267 goto out;
1268 }
1269 global.ssl_lim = atol(args[1]);
1270 }
William Lallemandd85f9172012-11-09 17:05:39 +01001271 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001272 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1273 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001274 if (*(args[1]) == 0) {
1275 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1276 err_code |= ERR_ALERT | ERR_FATAL;
1277 goto out;
1278 }
1279 global.comp_rate_lim = atoi(args[1]) * 1024;
1280 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001281 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001282 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1283 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001284 if (global.maxpipes != 0) {
1285 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001286 err_code |= ERR_ALERT;
1287 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001288 }
1289 if (*(args[1]) == 0) {
1290 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001291 err_code |= ERR_ALERT | ERR_FATAL;
1292 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001293 }
1294 global.maxpipes = atol(args[1]);
1295 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001296 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001297 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1298 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001299 if (*(args[1]) == 0) {
1300 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1301 err_code |= ERR_ALERT | ERR_FATAL;
1302 goto out;
1303 }
William Lallemande3a7d992012-11-20 11:25:20 +01001304 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001305 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001306 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001307 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1308 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001309 if (*(args[1]) == 0) {
1310 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1311 err_code |= ERR_ALERT | ERR_FATAL;
1312 goto out;
1313 }
1314 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001315 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001316 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1317 err_code |= ERR_ALERT | ERR_FATAL;
1318 goto out;
1319 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001320 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001321
Willy Tarreaubaaee002006-06-26 02:48:02 +02001322 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001323 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1324 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001325 if (global.rlimit_nofile != 0) {
1326 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001327 err_code |= ERR_ALERT;
1328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001329 }
1330 if (*(args[1]) == 0) {
1331 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001332 err_code |= ERR_ALERT | ERR_FATAL;
1333 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001334 }
1335 global.rlimit_nofile = atol(args[1]);
1336 }
1337 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001338 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001340 if (global.chroot != NULL) {
1341 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001342 err_code |= ERR_ALERT;
1343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001344 }
1345 if (*(args[1]) == 0) {
1346 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001347 err_code |= ERR_ALERT | ERR_FATAL;
1348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 }
1350 global.chroot = strdup(args[1]);
1351 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001352 else if (!strcmp(args[0], "description")) {
1353 int i, len=0;
1354 char *d;
1355
1356 if (!*args[1]) {
1357 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1358 file, linenum, args[0]);
1359 err_code |= ERR_ALERT | ERR_FATAL;
1360 goto out;
1361 }
1362
Willy Tarreau348acfe2014-04-14 15:00:39 +02001363 for (i = 1; *args[i]; i++)
1364 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001365
1366 if (global.desc)
1367 free(global.desc);
1368
1369 global.desc = d = (char *)calloc(1, len);
1370
Willy Tarreau348acfe2014-04-14 15:00:39 +02001371 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1372 for (i = 2; *args[i]; i++)
1373 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001374 }
1375 else if (!strcmp(args[0], "node")) {
1376 int i;
1377 char c;
1378
William Lallemand1a748ae2015-05-19 16:37:23 +02001379 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1380 goto out;
1381
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001382 for (i=0; args[1][i]; i++) {
1383 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001384 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1385 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001386 break;
1387 }
1388
1389 if (!i || args[1][i]) {
1390 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1391 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1392 file, linenum, args[0]);
1393 err_code |= ERR_ALERT | ERR_FATAL;
1394 goto out;
1395 }
1396
1397 if (global.node)
1398 free(global.node);
1399
1400 global.node = strdup(args[1]);
1401 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001402 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001403 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001405 if (global.pidfile != NULL) {
1406 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001407 err_code |= ERR_ALERT;
1408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001409 }
1410 if (*(args[1]) == 0) {
1411 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001412 err_code |= ERR_ALERT | ERR_FATAL;
1413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414 }
1415 global.pidfile = strdup(args[1]);
1416 }
Emeric Bruned760922010-10-22 17:59:25 +02001417 else if (!strcmp(args[0], "unix-bind")) {
1418 int cur_arg = 1;
1419 while (*(args[cur_arg])) {
1420 if (!strcmp(args[cur_arg], "prefix")) {
1421 if (global.unix_bind.prefix != NULL) {
1422 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1423 err_code |= ERR_ALERT;
1424 cur_arg += 2;
1425 continue;
1426 }
1427
1428 if (*(args[cur_arg+1]) == 0) {
1429 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1430 err_code |= ERR_ALERT | ERR_FATAL;
1431 goto out;
1432 }
1433 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1434 cur_arg += 2;
1435 continue;
1436 }
1437
1438 if (!strcmp(args[cur_arg], "mode")) {
1439
1440 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1441 cur_arg += 2;
1442 continue;
1443 }
1444
1445 if (!strcmp(args[cur_arg], "uid")) {
1446
1447 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1448 cur_arg += 2;
1449 continue;
1450 }
1451
1452 if (!strcmp(args[cur_arg], "gid")) {
1453
1454 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1455 cur_arg += 2;
1456 continue;
1457 }
1458
1459 if (!strcmp(args[cur_arg], "user")) {
1460 struct passwd *user;
1461
1462 user = getpwnam(args[cur_arg + 1]);
1463 if (!user) {
1464 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1465 file, linenum, args[0], args[cur_arg + 1 ]);
1466 err_code |= ERR_ALERT | ERR_FATAL;
1467 goto out;
1468 }
1469
1470 global.unix_bind.ux.uid = user->pw_uid;
1471 cur_arg += 2;
1472 continue;
1473 }
1474
1475 if (!strcmp(args[cur_arg], "group")) {
1476 struct group *group;
1477
1478 group = getgrnam(args[cur_arg + 1]);
1479 if (!group) {
1480 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1481 file, linenum, args[0], args[cur_arg + 1 ]);
1482 err_code |= ERR_ALERT | ERR_FATAL;
1483 goto out;
1484 }
1485
1486 global.unix_bind.ux.gid = group->gr_gid;
1487 cur_arg += 2;
1488 continue;
1489 }
1490
Willy Tarreaub48f9582011-09-05 01:17:06 +02001491 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001492 file, linenum, args[0]);
1493 err_code |= ERR_ALERT | ERR_FATAL;
1494 goto out;
1495 }
1496 }
William Lallemand0f99e342011-10-12 17:50:54 +02001497 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1498 /* delete previous herited or defined syslog servers */
1499 struct logsrv *back;
1500 struct logsrv *tmp;
1501
1502 if (*(args[1]) != 0) {
1503 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1504 err_code |= ERR_ALERT | ERR_FATAL;
1505 goto out;
1506 }
1507
1508 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1509 LIST_DEL(&tmp->list);
1510 free(tmp);
1511 }
1512 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001513 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001514 struct sockaddr_storage *sk;
1515 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001516 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001517 int arg = 0;
1518 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001519
William Lallemand1a748ae2015-05-19 16:37:23 +02001520 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1521 goto out;
1522
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523 if (*(args[1]) == 0 || *(args[2]) == 0) {
1524 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001525 err_code |= ERR_ALERT | ERR_FATAL;
1526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001527 }
William Lallemand0f99e342011-10-12 17:50:54 +02001528
1529 logsrv = calloc(1, sizeof(struct logsrv));
1530
Willy Tarreau18324f52014-06-27 18:10:07 +02001531 /* just after the address, a length may be specified */
1532 if (strcmp(args[arg+2], "len") == 0) {
1533 len = atoi(args[arg+3]);
1534 if (len < 80 || len > 65535) {
1535 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1536 file, linenum, args[arg+3]);
1537 err_code |= ERR_ALERT | ERR_FATAL;
1538 goto out;
1539 }
1540 logsrv->maxlen = len;
1541
1542 /* skip these two args */
1543 arg += 2;
1544 }
1545 else
1546 logsrv->maxlen = MAX_SYSLOG_LEN;
1547
1548 if (logsrv->maxlen > global.max_syslog_len) {
1549 global.max_syslog_len = logsrv->maxlen;
1550 logline = realloc(logline, global.max_syslog_len + 1);
1551 }
1552
William Lallemand1a748ae2015-05-19 16:37:23 +02001553 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1554 goto out;
1555
Willy Tarreau18324f52014-06-27 18:10:07 +02001556 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001557 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001558 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001559 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001560 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561 }
1562
William Lallemand0f99e342011-10-12 17:50:54 +02001563 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001564 if (*(args[arg+3])) {
1565 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001566 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001567 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001568 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001569 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 }
1571 }
1572
William Lallemand0f99e342011-10-12 17:50:54 +02001573 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001574 if (*(args[arg+4])) {
1575 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001576 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001577 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001578 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001579 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001580 }
1581 }
1582
Willy Tarreau902636f2013-03-10 19:44:48 +01001583 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001584 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001585 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001586 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001587 free(logsrv);
1588 goto out;
1589 }
1590 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001591
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001592 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001593 if (port1 != port2) {
1594 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1595 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001596 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001597 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001598 goto out;
1599 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001600
William Lallemand0f99e342011-10-12 17:50:54 +02001601 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001602 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001603 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001604 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605
William Lallemand0f99e342011-10-12 17:50:54 +02001606 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001607 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001608 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1609 char *name;
1610 int len;
1611
1612 if (global.log_send_hostname != NULL) {
1613 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1614 err_code |= ERR_ALERT;
1615 goto out;
1616 }
1617
1618 if (*(args[1]))
1619 name = args[1];
1620 else
1621 name = hostname;
1622
1623 len = strlen(name);
1624
1625 /* We'll add a space after the name to respect the log format */
1626 free(global.log_send_hostname);
1627 global.log_send_hostname = malloc(len + 2);
1628 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1629 }
Kevinm48936af2010-12-22 16:08:21 +00001630 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001631 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1632 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001633 if (*(args[1]) == 0) {
1634 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1635 err_code |= ERR_ALERT | ERR_FATAL;
1636 goto out;
1637 }
1638 free(global.log_tag);
1639 global.log_tag = strdup(args[1]);
1640 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001641 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001642 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1643 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001644 if (global.spread_checks != 0) {
1645 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001646 err_code |= ERR_ALERT;
1647 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001648 }
1649 if (*(args[1]) == 0) {
1650 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001651 err_code |= ERR_ALERT | ERR_FATAL;
1652 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001653 }
1654 global.spread_checks = atol(args[1]);
1655 if (global.spread_checks < 0 || global.spread_checks > 50) {
1656 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001657 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001658 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001659 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001660 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1661 const char *err;
1662 unsigned int val;
1663
William Lallemand1a748ae2015-05-19 16:37:23 +02001664 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1665 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001666 if (*(args[1]) == 0) {
1667 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1668 err_code |= ERR_ALERT | ERR_FATAL;
1669 goto out;
1670 }
1671
1672 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1673 if (err) {
1674 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1675 err_code |= ERR_ALERT | ERR_FATAL;
1676 }
1677 global.max_spread_checks = val;
1678 if (global.max_spread_checks < 0) {
1679 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1680 err_code |= ERR_ALERT | ERR_FATAL;
1681 }
1682 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001683 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1684#ifdef USE_CPU_AFFINITY
1685 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001686 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001687 unsigned long cpus = 0;
1688
1689 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001690 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001691 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001692 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001693 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001694 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001695 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001696 proc = atol(args[1]);
1697 if (proc >= 1 && proc <= LONGBITS)
1698 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001699 }
1700
1701 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001702 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",
1703 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001704 err_code |= ERR_ALERT | ERR_FATAL;
1705 goto out;
1706 }
1707
1708 cur_arg = 2;
1709 while (*args[cur_arg]) {
1710 unsigned int low, high;
1711
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001712 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001713 char *dash = strchr(args[cur_arg], '-');
1714
1715 low = high = str2uic(args[cur_arg]);
1716 if (dash)
1717 high = str2uic(dash + 1);
1718
1719 if (high < low) {
1720 unsigned int swap = low;
1721 low = high;
1722 high = swap;
1723 }
1724
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001725 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001726 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001727 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001728 err_code |= ERR_ALERT | ERR_FATAL;
1729 goto out;
1730 }
1731
1732 while (low <= high)
1733 cpus |= 1UL << low++;
1734 }
1735 else {
1736 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1737 file, linenum, args[0], args[cur_arg]);
1738 err_code |= ERR_ALERT | ERR_FATAL;
1739 goto out;
1740 }
1741 cur_arg++;
1742 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001743 for (i = 0; i < LONGBITS; i++)
1744 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001745 global.cpu_map[i] = cpus;
1746#else
1747 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1748 err_code |= ERR_ALERT | ERR_FATAL;
1749 goto out;
1750#endif
1751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001753 struct cfg_kw_list *kwl;
1754 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001755 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001756
1757 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1758 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1759 if (kwl->kw[index].section != CFG_GLOBAL)
1760 continue;
1761 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001762 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001763 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001764 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001765 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001766 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001767 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001768 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001769 err_code |= ERR_WARN;
1770 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001771 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001772 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001773 }
1774 }
1775 }
1776
Willy Tarreaubaaee002006-06-26 02:48:02 +02001777 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001778 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001779 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001780
Willy Tarreau058e9072009-07-20 09:30:05 +02001781 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001782 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001783 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001784}
1785
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001786void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001787{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001788 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001789 defproxy.mode = PR_MODE_TCP;
1790 defproxy.state = PR_STNEW;
1791 defproxy.maxconn = cfg_maxpconn;
1792 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001793 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001794
Simon Horman66183002013-02-23 10:16:43 +09001795 defproxy.defsrv.check.inter = DEF_CHKINTR;
1796 defproxy.defsrv.check.fastinter = 0;
1797 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001798 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1799 defproxy.defsrv.agent.fastinter = 0;
1800 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001801 defproxy.defsrv.check.rise = DEF_RISETIME;
1802 defproxy.defsrv.check.fall = DEF_FALLTIME;
1803 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1804 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001805 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001806 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001807 defproxy.defsrv.maxqueue = 0;
1808 defproxy.defsrv.minconn = 0;
1809 defproxy.defsrv.maxconn = 0;
1810 defproxy.defsrv.slowstart = 0;
1811 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1812 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1813 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001814
1815 defproxy.email_alert.level = LOG_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001816}
1817
Willy Tarreauade5ec42010-01-28 19:33:49 +01001818
Willy Tarreau63af98d2014-05-18 08:11:41 +02001819/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1820 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1821 * ERR_FATAL in case of error.
1822 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001823static int create_cond_regex_rule(const char *file, int line,
1824 struct proxy *px, int dir, int action, int flags,
1825 const char *cmd, const char *reg, const char *repl,
1826 const char **cond_start)
1827{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001828 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001829 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001830 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001831 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001832 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001833 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001834 int cs;
1835 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001836
1837 if (px == &defproxy) {
1838 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001839 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001840 goto err;
1841 }
1842
1843 if (*reg == 0) {
1844 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001845 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001846 goto err;
1847 }
1848
1849 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001850 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001851
Willy Tarreau5321c422010-01-28 20:35:13 +01001852 if (cond_start &&
1853 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001854 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1855 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1856 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001857 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001858 goto err;
1859 }
1860 }
1861 else if (cond_start && **cond_start) {
1862 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1863 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001864 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001865 goto err;
1866 }
1867
Willy Tarreau63af98d2014-05-18 08:11:41 +02001868 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001869 (dir == SMP_OPT_DIR_REQ) ?
1870 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1871 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1872 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001873
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001874 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001875 if (!preg) {
1876 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001877 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001878 goto err;
1879 }
1880
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001881 cs = !(flags & REG_ICASE);
1882 cap = !(flags & REG_NOSUB);
1883 error = NULL;
1884 if (!regex_comp(reg, preg, cs, cap, &error)) {
1885 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1886 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001887 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001888 goto err;
1889 }
1890
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001891 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001892 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001893 if (repl && err) {
1894 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1895 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001896 ret_code |= ERR_ALERT | ERR_FATAL;
1897 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001898 }
1899
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001900 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001901 ret_code |= ERR_WARN;
1902
1903 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001904
Willy Tarreau63af98d2014-05-18 08:11:41 +02001905 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001906 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001907 err:
1908 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001909 free(errmsg);
1910 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001911}
1912
Willy Tarreaubaaee002006-06-26 02:48:02 +02001913/*
William Lallemand51097192015-04-14 16:35:22 +02001914 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001915 * Returns the error code, 0 if OK, or any combination of :
1916 * - ERR_ABORT: must abort ASAP
1917 * - ERR_FATAL: we can continue parsing but not start the service
1918 * - ERR_WARN: a warning has been emitted
1919 * - ERR_ALERT: an alert has been emitted
1920 * Only the two first ones can stop processing, the two others are just
1921 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001922 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001923int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1924{
1925 static struct peers *curpeers = NULL;
1926 struct peer *newpeer = NULL;
1927 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001928 struct bind_conf *bind_conf;
1929 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001930 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001931 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001932
1933 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001934 if (!*args[1]) {
1935 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001936 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001937 goto out;
1938 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001939
William Lallemand6e62fb62015-04-28 16:55:23 +02001940 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1941 goto out;
1942
Emeric Brun32da3c42010-09-23 18:39:19 +02001943 err = invalid_char(args[1]);
1944 if (err) {
1945 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1946 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001947 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001948 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001949 }
1950
1951 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1952 /*
1953 * If there are two proxies with the same name only following
1954 * combinations are allowed:
1955 */
1956 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001957 Alert("Parsing [%s:%d]: peers section '%s' has the same name as another peers section declared at %s:%d.\n",
Emeric Brun32da3c42010-09-23 18:39:19 +02001958 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001959 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001960 }
1961 }
1962
1963 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1964 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1965 err_code |= ERR_ALERT | ERR_ABORT;
1966 goto out;
1967 }
1968
1969 curpeers->next = peers;
1970 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001971 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001972 curpeers->conf.line = linenum;
1973 curpeers->last_change = now.tv_sec;
1974 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001975 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001976 }
1977 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001978 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001979 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001980 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001981
1982 if (!*args[2]) {
1983 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1984 file, linenum, args[0]);
1985 err_code |= ERR_ALERT | ERR_FATAL;
1986 goto out;
1987 }
1988
1989 err = invalid_char(args[1]);
1990 if (err) {
1991 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1992 file, linenum, *err, args[1]);
1993 err_code |= ERR_ALERT | ERR_FATAL;
1994 goto out;
1995 }
1996
1997 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1998 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1999 err_code |= ERR_ALERT | ERR_ABORT;
2000 goto out;
2001 }
2002
2003 /* the peers are linked backwards first */
2004 curpeers->count++;
2005 newpeer->next = curpeers->remote;
2006 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002007 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002008 newpeer->conf.line = linenum;
2009
2010 newpeer->last_change = now.tv_sec;
2011 newpeer->id = strdup(args[1]);
2012
Willy Tarreau902636f2013-03-10 19:44:48 +01002013 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002014 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002015 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002016 err_code |= ERR_ALERT | ERR_FATAL;
2017 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002018 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002019
2020 proto = protocol_by_family(sk->ss_family);
2021 if (!proto || !proto->connect) {
2022 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2023 file, linenum, args[0], args[1]);
2024 err_code |= ERR_ALERT | ERR_FATAL;
2025 goto out;
2026 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002027
2028 if (port1 != port2) {
2029 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2030 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002031 err_code |= ERR_ALERT | ERR_FATAL;
2032 goto out;
2033 }
2034
Willy Tarreau2aa38802013-02-20 19:20:59 +01002035 if (!port1) {
2036 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2037 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002038 err_code |= ERR_ALERT | ERR_FATAL;
2039 goto out;
2040 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002041
Emeric Brun32da3c42010-09-23 18:39:19 +02002042 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002043 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002044 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002045 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002046
Emeric Brun32da3c42010-09-23 18:39:19 +02002047 if (strcmp(newpeer->id, localpeer) == 0) {
2048 /* Current is local peer, it define a frontend */
2049 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002050 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002051
2052 if (!curpeers->peers_fe) {
2053 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2054 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2055 err_code |= ERR_ALERT | ERR_ABORT;
2056 goto out;
2057 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002058
Willy Tarreau237250c2011-07-29 01:49:03 +02002059 init_new_proxy(curpeers->peers_fe);
2060 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002061 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002062 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2063 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002064 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002065
2066 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2067
Willy Tarreau902636f2013-03-10 19:44:48 +01002068 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2069 if (errmsg && *errmsg) {
2070 indent_msg(&errmsg, 2);
2071 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002072 }
2073 else
2074 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2075 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002076 err_code |= ERR_FATAL;
2077 goto out;
2078 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002079
2080 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002081 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002082 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2083 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002084 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002085 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002086 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002087 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002088 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2089 global.maxsock += l->maxconn;
2090 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002091 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002092 else {
2093 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2094 file, linenum, args[0], args[1],
2095 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2096 err_code |= ERR_FATAL;
2097 goto out;
2098 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002099 }
2100 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002101 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2102 curpeers->state = PR_STSTOPPED;
2103 }
2104 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2105 curpeers->state = PR_STNEW;
2106 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002107 else if (*args[0] != 0) {
2108 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2109 err_code |= ERR_ALERT | ERR_FATAL;
2110 goto out;
2111 }
2112
2113out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002114 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002115 return err_code;
2116}
2117
Simon Horman0d16a402015-01-30 11:22:58 +09002118
2119/*
William Lallemand51097192015-04-14 16:35:22 +02002120 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002121 * Returns the error code, 0 if OK, or any combination of :
2122 * - ERR_ABORT: must abort ASAP
2123 * - ERR_FATAL: we can continue parsing but not start the service
2124 * - ERR_WARN: a warning has been emitted
2125 * - ERR_ALERT: an alert has been emitted
2126 * Only the two first ones can stop processing, the two others are just
2127 * indicators.
2128 */
2129int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2130{
2131 static struct mailers *curmailers = NULL;
2132 struct mailer *newmailer = NULL;
2133 const char *err;
2134 int err_code = 0;
2135 char *errmsg = NULL;
2136
2137 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2138 if (!*args[1]) {
2139 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2140 err_code |= ERR_ALERT | ERR_ABORT;
2141 goto out;
2142 }
2143
2144 err = invalid_char(args[1]);
2145 if (err) {
2146 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2147 file, linenum, *err, args[0], args[1]);
2148 err_code |= ERR_ALERT | ERR_ABORT;
2149 goto out;
2150 }
2151
2152 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2153 /*
2154 * If there are two proxies with the same name only following
2155 * combinations are allowed:
2156 */
2157 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002158 Alert("Parsing [%s:%d]: mailers section '%s' has the same name as another mailers section declared at %s:%d.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002159 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002160 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002161 }
2162 }
2163
2164 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2165 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2166 err_code |= ERR_ALERT | ERR_ABORT;
2167 goto out;
2168 }
2169
2170 curmailers->next = mailers;
2171 mailers = curmailers;
2172 curmailers->conf.file = strdup(file);
2173 curmailers->conf.line = linenum;
2174 curmailers->id = strdup(args[1]);
2175 }
2176 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2177 struct sockaddr_storage *sk;
2178 int port1, port2;
2179 struct protocol *proto;
2180
2181 if (!*args[2]) {
2182 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2183 file, linenum, args[0]);
2184 err_code |= ERR_ALERT | ERR_FATAL;
2185 goto out;
2186 }
2187
2188 err = invalid_char(args[1]);
2189 if (err) {
2190 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2191 file, linenum, *err, args[1]);
2192 err_code |= ERR_ALERT | ERR_FATAL;
2193 goto out;
2194 }
2195
2196 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2197 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2198 err_code |= ERR_ALERT | ERR_ABORT;
2199 goto out;
2200 }
2201
2202 /* the mailers are linked backwards first */
2203 curmailers->count++;
2204 newmailer->next = curmailers->mailer_list;
2205 curmailers->mailer_list = newmailer;
2206 newmailer->mailers = curmailers;
2207 newmailer->conf.file = strdup(file);
2208 newmailer->conf.line = linenum;
2209
2210 newmailer->id = strdup(args[1]);
2211
2212 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2213 if (!sk) {
2214 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2215 err_code |= ERR_ALERT | ERR_FATAL;
2216 goto out;
2217 }
2218
2219 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002220 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2221 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002222 file, linenum, args[0], args[1]);
2223 err_code |= ERR_ALERT | ERR_FATAL;
2224 goto out;
2225 }
2226
2227 if (port1 != port2) {
2228 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2229 file, linenum, args[0], args[1], args[2]);
2230 err_code |= ERR_ALERT | ERR_FATAL;
2231 goto out;
2232 }
2233
2234 if (!port1) {
2235 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2236 file, linenum, args[0], args[1], args[2]);
2237 err_code |= ERR_ALERT | ERR_FATAL;
2238 goto out;
2239 }
2240
2241 newmailer->addr = *sk;
2242 newmailer->proto = proto;
2243 newmailer->xprt = &raw_sock;
2244 newmailer->sock_init_arg = NULL;
2245 } /* neither "mailer" nor "mailers" */
2246 else if (*args[0] != 0) {
2247 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2248 err_code |= ERR_ALERT | ERR_FATAL;
2249 goto out;
2250 }
2251
2252out:
2253 free(errmsg);
2254 return err_code;
2255}
2256
Simon Horman9dc49962015-01-30 11:22:59 +09002257static void free_email_alert(struct proxy *p)
2258{
2259 free(p->email_alert.mailers.name);
2260 p->email_alert.mailers.name = NULL;
2261 free(p->email_alert.from);
2262 p->email_alert.from = NULL;
2263 free(p->email_alert.to);
2264 p->email_alert.to = NULL;
2265 free(p->email_alert.myhostname);
2266 p->email_alert.myhostname = NULL;
2267}
2268
Willy Tarreau3842f002009-06-14 11:39:52 +02002269int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270{
2271 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002272 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002273 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002274 int rc;
2275 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002276 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002277 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002278 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002279 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002280 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002281
Willy Tarreau977b8e42006-12-29 14:19:17 +01002282 if (!strcmp(args[0], "listen"))
2283 rc = PR_CAP_LISTEN;
2284 else if (!strcmp(args[0], "frontend"))
2285 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002286 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002287 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002288 else
2289 rc = PR_CAP_NONE;
2290
2291 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 if (!*args[1]) {
2293 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2294 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2295 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002296 err_code |= ERR_ALERT | ERR_ABORT;
2297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002299
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002300 err = invalid_char(args[1]);
2301 if (err) {
2302 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2303 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002304 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002305 }
2306
Willy Tarreau8f50b682015-05-26 11:45:02 +02002307 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2308 if (curproxy) {
2309 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2310 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2311 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002312 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002313 }
2314
Willy Tarreaubaaee002006-06-26 02:48:02 +02002315 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2316 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002317 err_code |= ERR_ALERT | ERR_ABORT;
2318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002320
Willy Tarreau97cb7802010-01-03 20:23:58 +01002321 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002322 curproxy->next = proxy;
2323 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002324 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2325 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002326 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002327 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002328 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002329 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330
William Lallemand6e62fb62015-04-28 16:55:23 +02002331 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2332 if (curproxy->cap & PR_CAP_FE)
2333 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335 }
2336
2337 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002338 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002339 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002340
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002342 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002343 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002344 curproxy->no_options = defproxy.no_options;
2345 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002346 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002347 curproxy->except_net = defproxy.except_net;
2348 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002349 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002350 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002352 if (defproxy.fwdfor_hdr_len) {
2353 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2354 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2355 }
2356
Willy Tarreaub86db342009-11-30 11:50:16 +01002357 if (defproxy.orgto_hdr_len) {
2358 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2359 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2360 }
2361
Mark Lamourinec2247f02012-01-04 13:02:01 -05002362 if (defproxy.server_id_hdr_len) {
2363 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2364 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2365 }
2366
Willy Tarreau977b8e42006-12-29 14:19:17 +01002367 if (curproxy->cap & PR_CAP_FE) {
2368 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002369 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002370 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002371
2372 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002373 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2374 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002375
2376 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2377 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378
Willy Tarreau977b8e42006-12-29 14:19:17 +01002379 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002380 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002381 curproxy->fullconn = defproxy.fullconn;
2382 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002383 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002384 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002385
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002386 if (defproxy.check_req) {
2387 curproxy->check_req = calloc(1, defproxy.check_len);
2388 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2389 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002390 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002392 if (defproxy.expect_str) {
2393 curproxy->expect_str = strdup(defproxy.expect_str);
2394 if (defproxy.expect_regex) {
2395 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002396 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2397 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002398 }
2399 }
2400
Willy Tarreau67402132012-05-31 20:40:20 +02002401 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002402 if (defproxy.cookie_name)
2403 curproxy->cookie_name = strdup(defproxy.cookie_name);
2404 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002405 if (defproxy.cookie_domain)
2406 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002407
Willy Tarreau31936852010-10-06 16:59:56 +02002408 if (defproxy.cookie_maxidle)
2409 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2410
2411 if (defproxy.cookie_maxlife)
2412 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2413
Emeric Brun647caf12009-06-30 17:57:00 +02002414 if (defproxy.rdp_cookie_name)
2415 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2416 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2417
Willy Tarreau01732802007-11-01 22:48:15 +01002418 if (defproxy.url_param_name)
2419 curproxy->url_param_name = strdup(defproxy.url_param_name);
2420 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002421
Benoitaffb4812009-03-25 13:02:10 +01002422 if (defproxy.hh_name)
2423 curproxy->hh_name = strdup(defproxy.hh_name);
2424 curproxy->hh_len = defproxy.hh_len;
2425 curproxy->hh_match_domain = defproxy.hh_match_domain;
2426
Willy Tarreauef9a3602012-12-08 22:29:20 +01002427 if (defproxy.conn_src.iface_name)
2428 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2429 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002430 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002431#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002432 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002433#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002434 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002436 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002437 if (defproxy.capture_name)
2438 curproxy->capture_name = strdup(defproxy.capture_name);
2439 curproxy->capture_namelen = defproxy.capture_namelen;
2440 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002441 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442
Willy Tarreau977b8e42006-12-29 14:19:17 +01002443 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002444 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002445 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002446 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002447 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002448 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002449 curproxy->mon_net = defproxy.mon_net;
2450 curproxy->mon_mask = defproxy.mon_mask;
2451 if (defproxy.monitor_uri)
2452 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2453 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002454 if (defproxy.defbe.name)
2455 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002456
2457 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002458 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2459 if (curproxy->conf.logformat_string &&
2460 curproxy->conf.logformat_string != default_http_log_format &&
2461 curproxy->conf.logformat_string != default_tcp_log_format &&
2462 curproxy->conf.logformat_string != clf_http_log_format)
2463 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2464
2465 if (defproxy.conf.lfs_file) {
2466 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2467 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2468 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002469 }
2470
2471 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002472 curproxy->timeout.connect = defproxy.timeout.connect;
2473 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002474 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002475 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002476 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002477 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002478 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002479 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002480 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002481 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002482 }
2483
Willy Tarreaubaaee002006-06-26 02:48:02 +02002484 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002485 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002486
2487 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002488 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002489 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002490 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002491 LIST_INIT(&node->list);
2492 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2493 }
2494
Willy Tarreau62a61232013-04-12 18:13:46 +02002495 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2496 if (curproxy->conf.uniqueid_format_string)
2497 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2498
Willy Tarreau094af4e2015-01-07 15:03:42 +01002499 if (defproxy.log_tag)
2500 curproxy->log_tag = strdup(defproxy.log_tag);
2501
Willy Tarreau62a61232013-04-12 18:13:46 +02002502 if (defproxy.conf.uif_file) {
2503 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2504 curproxy->conf.uif_line = defproxy.conf.uif_line;
2505 }
William Lallemanda73203e2012-03-12 12:48:57 +01002506
2507 /* copy default header unique id */
2508 if (defproxy.header_unique_id)
2509 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2510
William Lallemand82fe75c2012-10-23 10:25:10 +02002511 /* default compression options */
2512 if (defproxy.comp != NULL) {
2513 curproxy->comp = calloc(1, sizeof(struct comp));
2514 curproxy->comp->algos = defproxy.comp->algos;
2515 curproxy->comp->types = defproxy.comp->types;
2516 }
2517
Willy Tarreaubaaee002006-06-26 02:48:02 +02002518 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002519 curproxy->conf.used_listener_id = EB_ROOT;
2520 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002521
Simon Horman98637e52014-06-20 12:30:16 +09002522 if (defproxy.check_path)
2523 curproxy->check_path = strdup(defproxy.check_path);
2524 if (defproxy.check_command)
2525 curproxy->check_command = strdup(defproxy.check_command);
2526
Simon Horman9dc49962015-01-30 11:22:59 +09002527 if (defproxy.email_alert.mailers.name)
2528 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2529 if (defproxy.email_alert.from)
2530 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2531 if (defproxy.email_alert.to)
2532 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2533 if (defproxy.email_alert.myhostname)
2534 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002535 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002536
Willy Tarreau93893792009-07-23 13:19:11 +02002537 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002538 }
2539 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2540 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002541 /* FIXME-20070101: we should do this too at the end of the
2542 * config parsing to free all default values.
2543 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002544 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2545 err_code |= ERR_ABORT;
2546 goto out;
2547 }
2548
Willy Tarreaua534fea2008-08-03 12:19:50 +02002549 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002550 free(defproxy.check_command);
2551 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002552 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002553 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002554 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002555 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002556 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002557 free(defproxy.capture_name);
2558 free(defproxy.monitor_uri);
2559 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002560 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002561 free(defproxy.fwdfor_hdr_name);
2562 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002563 free(defproxy.orgto_hdr_name);
2564 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002565 free(defproxy.server_id_hdr_name);
2566 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002567 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002568 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002569 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002570 free(defproxy.expect_regex);
2571 defproxy.expect_regex = NULL;
2572 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002573
Willy Tarreau62a61232013-04-12 18:13:46 +02002574 if (defproxy.conf.logformat_string != default_http_log_format &&
2575 defproxy.conf.logformat_string != default_tcp_log_format &&
2576 defproxy.conf.logformat_string != clf_http_log_format)
2577 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002578
Willy Tarreau62a61232013-04-12 18:13:46 +02002579 free(defproxy.conf.uniqueid_format_string);
2580 free(defproxy.conf.lfs_file);
2581 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002582 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002583 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002584
Willy Tarreaua534fea2008-08-03 12:19:50 +02002585 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002586 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002587
Willy Tarreaubaaee002006-06-26 02:48:02 +02002588 /* we cannot free uri_auth because it might already be used */
2589 init_default_instance();
2590 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002591 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2592 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002593 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 }
2596 else if (curproxy == NULL) {
2597 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002598 err_code |= ERR_ALERT | ERR_FATAL;
2599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002600 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002601
2602 /* update the current file and line being parsed */
2603 curproxy->conf.args.file = curproxy->conf.file;
2604 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002605
2606 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002607 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2608 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2609 if (err_code & ERR_FATAL)
2610 goto out;
2611 }
2612 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002613 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002614 int cur_arg;
2615
Willy Tarreaubaaee002006-06-26 02:48:02 +02002616 if (curproxy == &defproxy) {
2617 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002618 err_code |= ERR_ALERT | ERR_FATAL;
2619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002620 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002621 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002622 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002623
Willy Tarreau24709282013-03-10 21:32:12 +01002624 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002625 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002626 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002627 err_code |= ERR_ALERT | ERR_FATAL;
2628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002629 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002630
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002631 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002632
2633 /* use default settings for unix sockets */
2634 bind_conf->ux.uid = global.unix_bind.ux.uid;
2635 bind_conf->ux.gid = global.unix_bind.ux.gid;
2636 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002637
2638 /* NOTE: the following line might create several listeners if there
2639 * are comma-separated IPs or port ranges. So all further processing
2640 * will have to be applied to all listeners created after last_listen.
2641 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002642 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2643 if (errmsg && *errmsg) {
2644 indent_msg(&errmsg, 2);
2645 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002646 }
2647 else
2648 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2649 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
2652 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002653
Willy Tarreau4348fad2012-09-20 16:48:07 +02002654 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2655 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002656 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002657 }
2658
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002659 cur_arg = 2;
2660 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002661 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002662 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002663 char *err;
2664
Willy Tarreau26982662012-09-12 23:17:10 +02002665 kw = bind_find_kw(args[cur_arg]);
2666 if (kw) {
2667 char *err = NULL;
2668 int code;
2669
2670 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002671 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2672 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002673 cur_arg += 1 + kw->skip ;
2674 err_code |= ERR_ALERT | ERR_FATAL;
2675 goto out;
2676 }
2677
Willy Tarreau4348fad2012-09-20 16:48:07 +02002678 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002679 err_code |= code;
2680
2681 if (code) {
2682 if (err && *err) {
2683 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002684 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002685 }
2686 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002687 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2688 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002689 if (code & ERR_FATAL) {
2690 free(err);
2691 cur_arg += 1 + kw->skip;
2692 goto out;
2693 }
2694 }
2695 free(err);
2696 cur_arg += 1 + kw->skip;
2697 continue;
2698 }
2699
Willy Tarreau8638f482012-09-18 18:01:17 +02002700 err = NULL;
2701 if (!bind_dumped) {
2702 bind_dump_kws(&err);
2703 indent_msg(&err, 4);
2704 bind_dumped = 1;
2705 }
2706
2707 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2708 file, linenum, args[0], args[1], args[cur_arg],
2709 err ? " Registered keywords :" : "", err ? err : "");
2710 free(err);
2711
Willy Tarreau93893792009-07-23 13:19:11 +02002712 err_code |= ERR_ALERT | ERR_FATAL;
2713 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002714 }
Willy Tarreau93893792009-07-23 13:19:11 +02002715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002716 }
2717 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002718 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002719 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2720 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002721 err_code |= ERR_ALERT | ERR_FATAL;
2722 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002723 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002724 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002725 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002726
Willy Tarreaubaaee002006-06-26 02:48:02 +02002727 /* flush useless bits */
2728 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002729 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002730 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002731 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002732 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002733 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002734
William Lallemanddf1425a2015-04-28 20:17:49 +02002735 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2736 goto out;
2737
Willy Tarreau1c47f852006-07-09 08:22:27 +02002738 if (!*args[1]) {
2739 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2740 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002743 }
2744
Willy Tarreaua534fea2008-08-03 12:19:50 +02002745 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002746 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002747 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002748 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002749 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2750
Willy Tarreau93893792009-07-23 13:19:11 +02002751 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002752 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002753 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02002754 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2755 goto out;
2756
Willy Tarreaubaaee002006-06-26 02:48:02 +02002757 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2758 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2759 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2760 else {
2761 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002764 }
2765 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002766 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002767 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002768
2769 if (curproxy == &defproxy) {
2770 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2771 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002772 err_code |= ERR_ALERT | ERR_FATAL;
2773 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002774 }
2775
William Lallemanddf1425a2015-04-28 20:17:49 +02002776 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2777 goto out;
2778
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002779 if (!*args[1]) {
2780 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2781 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002782 err_code |= ERR_ALERT | ERR_FATAL;
2783 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002784 }
2785
2786 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002787 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02002788 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002789
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002790 if (curproxy->uuid <= 0) {
2791 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002792 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002793 err_code |= ERR_ALERT | ERR_FATAL;
2794 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002795 }
2796
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002797 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2798 if (node) {
2799 struct proxy *target = container_of(node, struct proxy, conf.id);
2800 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2801 file, linenum, proxy_type_str(curproxy), curproxy->id,
2802 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2803 err_code |= ERR_ALERT | ERR_FATAL;
2804 goto out;
2805 }
2806 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002807 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002808 else if (!strcmp(args[0], "description")) {
2809 int i, len=0;
2810 char *d;
2811
Cyril Bonté99ed3272010-01-24 23:29:44 +01002812 if (curproxy == &defproxy) {
2813 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2814 file, linenum, args[0]);
2815 err_code |= ERR_ALERT | ERR_FATAL;
2816 goto out;
2817 }
2818
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002819 if (!*args[1]) {
2820 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2821 file, linenum, args[0]);
2822 return -1;
2823 }
2824
Willy Tarreau348acfe2014-04-14 15:00:39 +02002825 for (i = 1; *args[i]; i++)
2826 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002827
2828 d = (char *)calloc(1, len);
2829 curproxy->desc = d;
2830
Willy Tarreau348acfe2014-04-14 15:00:39 +02002831 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2832 for (i = 2; *args[i]; i++)
2833 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002834
2835 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002836 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02002837 if (alertif_too_many_args(0, file, linenum, args, &err_code))
2838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002839 curproxy->state = PR_STSTOPPED;
2840 }
2841 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02002842 if (alertif_too_many_args(0, file, linenum, args, &err_code))
2843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002844 curproxy->state = PR_STNEW;
2845 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002846 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2847 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002848 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002849
2850 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002851 unsigned int low, high;
2852
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002853 if (strcmp(args[cur_arg], "all") == 0) {
2854 set = 0;
2855 break;
2856 }
2857 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002858 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002859 }
2860 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002861 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002862 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002863 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002864 char *dash = strchr(args[cur_arg], '-');
2865
2866 low = high = str2uic(args[cur_arg]);
2867 if (dash)
2868 high = str2uic(dash + 1);
2869
2870 if (high < low) {
2871 unsigned int swap = low;
2872 low = high;
2873 high = swap;
2874 }
2875
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002876 if (low < 1 || high > LONGBITS) {
2877 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2878 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002881 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002882 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002883 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002884 }
2885 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002886 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2887 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002888 err_code |= ERR_ALERT | ERR_FATAL;
2889 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002890 }
2891 cur_arg++;
2892 }
2893 curproxy->bind_proc = set;
2894 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002895 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002896 if (curproxy == &defproxy) {
2897 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002898 err_code |= ERR_ALERT | ERR_FATAL;
2899 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002900 }
2901
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002902 err = invalid_char(args[1]);
2903 if (err) {
2904 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2905 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002906 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002907 }
2908
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002909 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002910 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2911 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002914 }
2915 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2917 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002918
Willy Tarreau977b8e42006-12-29 14:19:17 +01002919 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002920 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002921
Willy Tarreaubaaee002006-06-26 02:48:02 +02002922 if (*(args[1]) == 0) {
2923 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2924 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002925 err_code |= ERR_ALERT | ERR_FATAL;
2926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002927 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002928
Willy Tarreau67402132012-05-31 20:40:20 +02002929 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002930 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002931 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002932 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002933 curproxy->cookie_name = strdup(args[1]);
2934 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002935
Willy Tarreaubaaee002006-06-26 02:48:02 +02002936 cur_arg = 2;
2937 while (*(args[cur_arg])) {
2938 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002939 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002940 }
2941 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002942 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002943 }
2944 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002945 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002946 }
2947 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002948 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002949 }
2950 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002951 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002952 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002953 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002954 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002955 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002956 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002957 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002958 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002959 else if (!strcmp(args[cur_arg], "httponly")) {
2960 curproxy->ck_opts |= PR_CK_HTTPONLY;
2961 }
2962 else if (!strcmp(args[cur_arg], "secure")) {
2963 curproxy->ck_opts |= PR_CK_SECURE;
2964 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002965 else if (!strcmp(args[cur_arg], "domain")) {
2966 if (!*args[cur_arg + 1]) {
2967 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2968 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002969 err_code |= ERR_ALERT | ERR_FATAL;
2970 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002971 }
2972
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002973 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002974 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002975 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2976 " dots nor does not start with a dot."
2977 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002978 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002979 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002980 }
2981
2982 err = invalid_domainchar(args[cur_arg + 1]);
2983 if (err) {
2984 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2985 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002986 err_code |= ERR_ALERT | ERR_FATAL;
2987 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002988 }
2989
Willy Tarreau68a897b2009-12-03 23:28:34 +01002990 if (!curproxy->cookie_domain) {
2991 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2992 } else {
2993 /* one domain was already specified, add another one by
2994 * building the string which will be returned along with
2995 * the cookie.
2996 */
2997 char *new_ptr;
2998 int new_len = strlen(curproxy->cookie_domain) +
2999 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3000 new_ptr = malloc(new_len);
3001 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3002 free(curproxy->cookie_domain);
3003 curproxy->cookie_domain = new_ptr;
3004 }
Willy Tarreau31936852010-10-06 16:59:56 +02003005 cur_arg++;
3006 }
3007 else if (!strcmp(args[cur_arg], "maxidle")) {
3008 unsigned int maxidle;
3009 const char *res;
3010
3011 if (!*args[cur_arg + 1]) {
3012 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3013 file, linenum, args[cur_arg]);
3014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
3016 }
3017
3018 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3019 if (res) {
3020 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3021 file, linenum, *res, args[cur_arg]);
3022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
3024 }
3025 curproxy->cookie_maxidle = maxidle;
3026 cur_arg++;
3027 }
3028 else if (!strcmp(args[cur_arg], "maxlife")) {
3029 unsigned int maxlife;
3030 const char *res;
3031
3032 if (!*args[cur_arg + 1]) {
3033 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3034 file, linenum, args[cur_arg]);
3035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
3037 }
3038
3039 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3040 if (res) {
3041 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3042 file, linenum, *res, args[cur_arg]);
3043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
3045 }
3046 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003047 cur_arg++;
3048 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003049 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003050 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 +02003051 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003052 err_code |= ERR_ALERT | ERR_FATAL;
3053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003054 }
3055 cur_arg++;
3056 }
Willy Tarreau67402132012-05-31 20:40:20 +02003057 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3059 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003060 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061 }
3062
Willy Tarreau67402132012-05-31 20:40:20 +02003063 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003064 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3065 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003066 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003068
Willy Tarreau67402132012-05-31 20:40:20 +02003069 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003070 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3071 file, linenum);
3072 err_code |= ERR_ALERT | ERR_FATAL;
3073 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003074 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003075 else if (!strcmp(args[0], "email-alert")) {
3076 if (*(args[1]) == 0) {
3077 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3078 file, linenum, args[0]);
3079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
3081 }
3082
3083 if (!strcmp(args[1], "from")) {
3084 if (*(args[1]) == 0) {
3085 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3086 file, linenum, args[1]);
3087 err_code |= ERR_ALERT | ERR_FATAL;
3088 goto out;
3089 }
3090 free(curproxy->email_alert.from);
3091 curproxy->email_alert.from = strdup(args[2]);
3092 }
3093 else if (!strcmp(args[1], "mailers")) {
3094 if (*(args[1]) == 0) {
3095 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3096 file, linenum, args[1]);
3097 err_code |= ERR_ALERT | ERR_FATAL;
3098 goto out;
3099 }
3100 free(curproxy->email_alert.mailers.name);
3101 curproxy->email_alert.mailers.name = strdup(args[2]);
3102 }
3103 else if (!strcmp(args[1], "myhostname")) {
3104 if (*(args[1]) == 0) {
3105 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3106 file, linenum, args[1]);
3107 err_code |= ERR_ALERT | ERR_FATAL;
3108 goto out;
3109 }
3110 free(curproxy->email_alert.myhostname);
3111 curproxy->email_alert.myhostname = strdup(args[2]);
3112 }
Simon Horman64e34162015-02-06 11:11:57 +09003113 else if (!strcmp(args[1], "level")) {
3114 curproxy->email_alert.level = get_log_level(args[2]);
3115 if (curproxy->email_alert.level < 0) {
3116 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3117 file, linenum, args[1], args[2]);
3118 err_code |= ERR_ALERT | ERR_FATAL;
3119 goto out;
3120 }
3121 }
Simon Horman9dc49962015-01-30 11:22:59 +09003122 else if (!strcmp(args[1], "to")) {
3123 if (*(args[1]) == 0) {
3124 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3125 file, linenum, args[1]);
3126 err_code |= ERR_ALERT | ERR_FATAL;
3127 goto out;
3128 }
3129 free(curproxy->email_alert.to);
3130 curproxy->email_alert.to = strdup(args[2]);
3131 }
3132 else {
3133 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3134 file, linenum, args[1]);
3135 err_code |= ERR_ALERT | ERR_FATAL;
3136 goto out;
3137 }
Simon Horman64e34162015-02-06 11:11:57 +09003138 /* Indicate that the email_alert is at least partially configured */
3139 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003140 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003141 else if (!strcmp(args[0], "external-check")) {
3142 if (*(args[1]) == 0) {
3143 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3144 file, linenum, args[0]);
3145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
3147 }
3148
3149 if (!strcmp(args[1], "command")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003150 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3151 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003152 if (*(args[1]) == 0) {
3153 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3154 file, linenum, args[1]);
3155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
3157 }
3158 free(curproxy->check_command);
3159 curproxy->check_command = strdup(args[2]);
3160 }
3161 else if (!strcmp(args[1], "path")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003162 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3163 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003164 if (*(args[1]) == 0) {
3165 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3166 file, linenum, args[1]);
3167 err_code |= ERR_ALERT | ERR_FATAL;
3168 goto out;
3169 }
3170 free(curproxy->check_path);
3171 curproxy->check_path = strdup(args[2]);
3172 }
3173 else {
3174 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3175 file, linenum, args[1]);
3176 err_code |= ERR_ALERT | ERR_FATAL;
3177 goto out;
3178 }
3179 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003180 else if (!strcmp(args[0], "persist")) { /* persist */
3181 if (*(args[1]) == 0) {
3182 Alert("parsing [%s:%d] : missing persist method.\n",
3183 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003186 }
3187
3188 if (!strncmp(args[1], "rdp-cookie", 10)) {
3189 curproxy->options2 |= PR_O2_RDPC_PRST;
3190
Emeric Brunb982a3d2010-01-04 15:45:53 +01003191 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003192 const char *beg, *end;
3193
3194 beg = args[1] + 11;
3195 end = strchr(beg, ')');
3196
William Lallemanddf1425a2015-04-28 20:17:49 +02003197 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3198 goto out;
3199
Emeric Brun647caf12009-06-30 17:57:00 +02003200 if (!end || end == beg) {
3201 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3202 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003205 }
3206
3207 free(curproxy->rdp_cookie_name);
3208 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3209 curproxy->rdp_cookie_len = end-beg;
3210 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003211 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003212 free(curproxy->rdp_cookie_name);
3213 curproxy->rdp_cookie_name = strdup("msts");
3214 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3215 }
3216 else { /* syntax */
3217 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3218 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003219 err_code |= ERR_ALERT | ERR_FATAL;
3220 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003221 }
3222 }
3223 else {
3224 Alert("parsing [%s:%d] : unknown persist method.\n",
3225 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003226 err_code |= ERR_ALERT | ERR_FATAL;
3227 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003228 }
3229 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003230 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003231 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003233 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 Tarreau977b8e42006-12-29 14:19:17 +01003239 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003240 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003241
Willy Tarreaubaaee002006-06-26 02:48:02 +02003242 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003243 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003244 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003247 }
3248 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003249 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 curproxy->appsession_name = strdup(args[1]);
3251 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3252 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003253 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3254 if (err) {
3255 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3256 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003257 err_code |= ERR_ALERT | ERR_FATAL;
3258 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003259 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003260 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003261
Willy Tarreau51041c72007-09-09 21:56:53 +02003262 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3263 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003264 err_code |= ERR_ALERT | ERR_ABORT;
3265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003267
3268 cur_arg = 6;
3269 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003270 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3271 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003272 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003273 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003274 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003275 } else if (!strcmp(args[cur_arg], "prefix")) {
3276 curproxy->options2 |= PR_O2_AS_PFX;
3277 } else if (!strcmp(args[cur_arg], "mode")) {
3278 if (!*args[cur_arg + 1]) {
3279 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3280 file, linenum, args[0], args[cur_arg]);
3281 err_code |= ERR_ALERT | ERR_FATAL;
3282 goto out;
3283 }
3284
3285 cur_arg++;
3286 if (!strcmp(args[cur_arg], "query-string")) {
3287 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3288 curproxy->options2 |= PR_O2_AS_M_QS;
3289 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3290 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3291 curproxy->options2 |= PR_O2_AS_M_PP;
3292 } else {
3293 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
3296 }
3297 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003298 cur_arg++;
3299 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 } /* Url App Session */
3301 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003302 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003303 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003304
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003306 if (curproxy == &defproxy) {
3307 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3308 err_code |= ERR_ALERT | ERR_FATAL;
3309 goto out;
3310 }
3311
William Lallemand1a748ae2015-05-19 16:37:23 +02003312 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3313 goto out;
3314
Willy Tarreaubaaee002006-06-26 02:48:02 +02003315 if (*(args[4]) == 0) {
3316 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3317 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003320 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003321 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003322 curproxy->capture_name = strdup(args[2]);
3323 curproxy->capture_namelen = strlen(curproxy->capture_name);
3324 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003325 curproxy->to_log |= LW_COOKIE;
3326 }
3327 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3328 struct cap_hdr *hdr;
3329
3330 if (curproxy == &defproxy) {
3331 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 +02003332 err_code |= ERR_ALERT | ERR_FATAL;
3333 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003334 }
3335
William Lallemand1a748ae2015-05-19 16:37:23 +02003336 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3337 goto out;
3338
Willy Tarreaubaaee002006-06-26 02:48:02 +02003339 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3340 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3341 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003342 err_code |= ERR_ALERT | ERR_FATAL;
3343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003344 }
3345
3346 hdr = calloc(sizeof(struct cap_hdr), 1);
3347 hdr->next = curproxy->req_cap;
3348 hdr->name = strdup(args[3]);
3349 hdr->namelen = strlen(args[3]);
3350 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003351 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003352 hdr->index = curproxy->nb_req_cap++;
3353 curproxy->req_cap = hdr;
3354 curproxy->to_log |= LW_REQHDR;
3355 }
3356 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3357 struct cap_hdr *hdr;
3358
3359 if (curproxy == &defproxy) {
3360 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 +02003361 err_code |= ERR_ALERT | ERR_FATAL;
3362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 }
3364
William Lallemand1a748ae2015-05-19 16:37:23 +02003365 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3366 goto out;
3367
Willy Tarreaubaaee002006-06-26 02:48:02 +02003368 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3369 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3370 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003371 err_code |= ERR_ALERT | ERR_FATAL;
3372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373 }
3374 hdr = calloc(sizeof(struct cap_hdr), 1);
3375 hdr->next = curproxy->rsp_cap;
3376 hdr->name = strdup(args[3]);
3377 hdr->namelen = strlen(args[3]);
3378 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003379 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003380 hdr->index = curproxy->nb_rsp_cap++;
3381 curproxy->rsp_cap = hdr;
3382 curproxy->to_log |= LW_RSPHDR;
3383 }
3384 else {
3385 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3386 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003387 err_code |= ERR_ALERT | ERR_FATAL;
3388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003389 }
3390 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003391 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003392 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003393 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003394
William Lallemanddf1425a2015-04-28 20:17:49 +02003395 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3396 goto out;
3397
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398 if (*(args[1]) == 0) {
3399 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3400 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003401 err_code |= ERR_ALERT | ERR_FATAL;
3402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003403 }
3404 curproxy->conn_retries = atol(args[1]);
3405 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003406 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003407 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003408
3409 if (curproxy == &defproxy) {
3410 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3411 err_code |= ERR_ALERT | ERR_FATAL;
3412 goto out;
3413 }
3414
Willy Tarreau20b0de52012-12-24 15:45:22 +01003415 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3416 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3417 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3418 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003419 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003420 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3421 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 +01003422 file, linenum, args[0]);
3423 err_code |= ERR_WARN;
3424 }
3425
Willy Tarreauff011f22011-01-06 17:51:27 +01003426 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003427
Willy Tarreauff011f22011-01-06 17:51:27 +01003428 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003429 err_code |= ERR_ALERT | ERR_ABORT;
3430 goto out;
3431 }
3432
Willy Tarreau5002f572014-04-23 01:32:02 +02003433 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003434 err_code |= warnif_cond_conflicts(rule->cond,
3435 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3436 file, linenum);
3437
Willy Tarreauff011f22011-01-06 17:51:27 +01003438 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003439 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003440 else if (!strcmp(args[0], "http-response")) { /* response access control */
3441 struct http_res_rule *rule;
3442
3443 if (curproxy == &defproxy) {
3444 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3445 err_code |= ERR_ALERT | ERR_FATAL;
3446 goto out;
3447 }
3448
3449 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3450 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3451 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3452 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3453 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3454 file, linenum, args[0]);
3455 err_code |= ERR_WARN;
3456 }
3457
3458 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3459
3460 if (!rule) {
3461 err_code |= ERR_ALERT | ERR_ABORT;
3462 goto out;
3463 }
3464
3465 err_code |= warnif_cond_conflicts(rule->cond,
3466 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3467 file, linenum);
3468
3469 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3470 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003471 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3472 /* set the header name and length into the proxy structure */
3473 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3474 err_code |= ERR_WARN;
3475
3476 if (!*args[1]) {
3477 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3478 file, linenum, args[0]);
3479 err_code |= ERR_ALERT | ERR_FATAL;
3480 goto out;
3481 }
3482
3483 /* set the desired header name */
3484 free(curproxy->server_id_hdr_name);
3485 curproxy->server_id_hdr_name = strdup(args[1]);
3486 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3487 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003488 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003489 struct http_req_rule *rule;
3490
Willy Tarreaub099aca2008-10-12 17:26:37 +02003491 if (curproxy == &defproxy) {
3492 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003493 err_code |= ERR_ALERT | ERR_FATAL;
3494 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003495 }
3496
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003497 /* emulate "block" using "http-request block". Since these rules are supposed to
3498 * be processed before all http-request rules, we put them into their own list
3499 * and will insert them at the end.
3500 */
3501 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3502 if (!rule) {
3503 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003504 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003505 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003506 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3507 err_code |= warnif_cond_conflicts(rule->cond,
3508 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3509 file, linenum);
3510 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003511
3512 if (!already_warned(WARN_BLOCK_DEPRECATED))
3513 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]);
3514
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003515 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003516 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003517 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003518
Cyril Bonté99ed3272010-01-24 23:29:44 +01003519 if (curproxy == &defproxy) {
3520 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3521 err_code |= ERR_ALERT | ERR_FATAL;
3522 goto out;
3523 }
3524
Willy Tarreaube4653b2015-05-28 15:26:58 +02003525 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003526 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3527 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003528 err_code |= ERR_ALERT | ERR_FATAL;
3529 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003530 }
3531
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003532 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003533 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003534 err_code |= warnif_cond_conflicts(rule->cond,
3535 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3536 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003537 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003538 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003539 struct switching_rule *rule;
3540
Willy Tarreaub099aca2008-10-12 17:26:37 +02003541 if (curproxy == &defproxy) {
3542 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003543 err_code |= ERR_ALERT | ERR_FATAL;
3544 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003545 }
3546
Willy Tarreau55ea7572007-06-17 19:56:27 +02003547 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003548 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003549
3550 if (*(args[1]) == 0) {
3551 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003552 err_code |= ERR_ALERT | ERR_FATAL;
3553 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003554 }
3555
Willy Tarreauf51658d2014-04-23 01:21:56 +02003556 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3557 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3558 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3559 file, linenum, errmsg);
3560 err_code |= ERR_ALERT | ERR_FATAL;
3561 goto out;
3562 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003563
Willy Tarreauf51658d2014-04-23 01:21:56 +02003564 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003565 }
3566
3567 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3568 rule->cond = cond;
3569 rule->be.name = strdup(args[1]);
3570 LIST_INIT(&rule->list);
3571 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3572 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003573 else if (strcmp(args[0], "use-server") == 0) {
3574 struct server_rule *rule;
3575
3576 if (curproxy == &defproxy) {
3577 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3578 err_code |= ERR_ALERT | ERR_FATAL;
3579 goto out;
3580 }
3581
3582 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3583 err_code |= ERR_WARN;
3584
3585 if (*(args[1]) == 0) {
3586 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3587 err_code |= ERR_ALERT | ERR_FATAL;
3588 goto out;
3589 }
3590
3591 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3592 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3593 file, linenum, args[0]);
3594 err_code |= ERR_ALERT | ERR_FATAL;
3595 goto out;
3596 }
3597
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003598 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3599 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3600 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003601 err_code |= ERR_ALERT | ERR_FATAL;
3602 goto out;
3603 }
3604
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003605 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003606
3607 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3608 rule->cond = cond;
3609 rule->srv.name = strdup(args[1]);
3610 LIST_INIT(&rule->list);
3611 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3612 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3613 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003614 else if ((!strcmp(args[0], "force-persist")) ||
3615 (!strcmp(args[0], "ignore-persist"))) {
3616 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003617
3618 if (curproxy == &defproxy) {
3619 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
3622 }
3623
3624 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3625 err_code |= ERR_WARN;
3626
Willy Tarreauef6494c2010-01-28 17:12:36 +01003627 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003628 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3629 file, linenum, args[0]);
3630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
3632 }
3633
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003634 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3635 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3636 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003637 err_code |= ERR_ALERT | ERR_FATAL;
3638 goto out;
3639 }
3640
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003641 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3642 * where force-persist is applied.
3643 */
3644 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003645
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003646 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003647 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003648 if (!strcmp(args[0], "force-persist")) {
3649 rule->type = PERSIST_TYPE_FORCE;
3650 } else {
3651 rule->type = PERSIST_TYPE_IGNORE;
3652 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003653 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003654 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003655 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003656 else if (!strcmp(args[0], "stick-table")) {
3657 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003658 struct proxy *other;
3659
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003660 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003661 if (other) {
3662 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3663 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3664 err_code |= ERR_ALERT | ERR_FATAL;
3665 goto out;
3666 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003667
Emeric Brun32da3c42010-09-23 18:39:19 +02003668 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003669 curproxy->table.type = (unsigned int)-1;
3670 while (*args[myidx]) {
3671 const char *err;
3672
3673 if (strcmp(args[myidx], "size") == 0) {
3674 myidx++;
3675 if (!*(args[myidx])) {
3676 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3677 file, linenum, args[myidx-1]);
3678 err_code |= ERR_ALERT | ERR_FATAL;
3679 goto out;
3680 }
3681 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3682 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3683 file, linenum, *err, args[myidx-1]);
3684 err_code |= ERR_ALERT | ERR_FATAL;
3685 goto out;
3686 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003687 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003688 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003689 else if (strcmp(args[myidx], "peers") == 0) {
3690 myidx++;
Godbach50523162013-12-11 19:48:57 +08003691 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003692 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3693 file, linenum, args[myidx-1]);
3694 err_code |= ERR_ALERT | ERR_FATAL;
3695 goto out;
Godbach50523162013-12-11 19:48:57 +08003696 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003697 curproxy->table.peers.name = strdup(args[myidx++]);
3698 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003699 else if (strcmp(args[myidx], "expire") == 0) {
3700 myidx++;
3701 if (!*(args[myidx])) {
3702 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3703 file, linenum, args[myidx-1]);
3704 err_code |= ERR_ALERT | ERR_FATAL;
3705 goto out;
3706 }
3707 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3708 if (err) {
3709 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3710 file, linenum, *err, args[myidx-1]);
3711 err_code |= ERR_ALERT | ERR_FATAL;
3712 goto out;
3713 }
3714 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003715 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003716 }
3717 else if (strcmp(args[myidx], "nopurge") == 0) {
3718 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003719 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003720 }
3721 else if (strcmp(args[myidx], "type") == 0) {
3722 myidx++;
3723 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3724 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3725 file, linenum, args[myidx]);
3726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
3728 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003729 /* myidx already points to next arg */
3730 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003731 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003732 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003733 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003734
3735 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003736 nw = args[myidx];
3737 while (*nw) {
3738 /* the "store" keyword supports a comma-separated list */
3739 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003740 sa = NULL; /* store arg */
3741 while (*nw && *nw != ',') {
3742 if (*nw == '(') {
3743 *nw = 0;
3744 sa = ++nw;
3745 while (*nw != ')') {
3746 if (!*nw) {
3747 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3748 file, linenum, args[0], cw);
3749 err_code |= ERR_ALERT | ERR_FATAL;
3750 goto out;
3751 }
3752 nw++;
3753 }
3754 *nw = '\0';
3755 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003756 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003757 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003758 if (*nw)
3759 *nw++ = '\0';
3760 type = stktable_get_data_type(cw);
3761 if (type < 0) {
3762 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3763 file, linenum, args[0], cw);
3764 err_code |= ERR_ALERT | ERR_FATAL;
3765 goto out;
3766 }
Willy Tarreauac782882010-06-20 10:41:54 +02003767
3768 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3769 switch (err) {
3770 case PE_NONE: break;
3771 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003772 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3773 file, linenum, args[0], cw);
3774 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003775 break;
3776
3777 case PE_ARG_MISSING:
3778 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3779 file, linenum, args[0], cw);
3780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
3782
3783 case PE_ARG_NOT_USED:
3784 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3785 file, linenum, args[0], cw);
3786 err_code |= ERR_ALERT | ERR_FATAL;
3787 goto out;
3788
3789 default:
3790 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3791 file, linenum, args[0], cw);
3792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003794 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003795 }
3796 myidx++;
3797 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003798 else {
3799 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3800 file, linenum, args[myidx]);
3801 err_code |= ERR_ALERT | ERR_FATAL;
3802 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003803 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003804 }
3805
3806 if (!curproxy->table.size) {
3807 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3808 file, linenum);
3809 err_code |= ERR_ALERT | ERR_FATAL;
3810 goto out;
3811 }
3812
3813 if (curproxy->table.type == (unsigned int)-1) {
3814 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3815 file, linenum);
3816 err_code |= ERR_ALERT | ERR_FATAL;
3817 goto out;
3818 }
3819 }
3820 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003821 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003822 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003823 int myidx = 0;
3824 const char *name = NULL;
3825 int flags;
3826
3827 if (curproxy == &defproxy) {
3828 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3829 err_code |= ERR_ALERT | ERR_FATAL;
3830 goto out;
3831 }
3832
3833 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3834 err_code |= ERR_WARN;
3835 goto out;
3836 }
3837
3838 myidx++;
3839 if ((strcmp(args[myidx], "store") == 0) ||
3840 (strcmp(args[myidx], "store-request") == 0)) {
3841 myidx++;
3842 flags = STK_IS_STORE;
3843 }
3844 else if (strcmp(args[myidx], "store-response") == 0) {
3845 myidx++;
3846 flags = STK_IS_STORE | STK_ON_RSP;
3847 }
3848 else if (strcmp(args[myidx], "match") == 0) {
3849 myidx++;
3850 flags = STK_IS_MATCH;
3851 }
3852 else if (strcmp(args[myidx], "on") == 0) {
3853 myidx++;
3854 flags = STK_IS_MATCH | STK_IS_STORE;
3855 }
3856 else {
3857 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
3860 }
3861
3862 if (*(args[myidx]) == 0) {
3863 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3864 err_code |= ERR_ALERT | ERR_FATAL;
3865 goto out;
3866 }
3867
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003868 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003869 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003870 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003871 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
3874 }
3875
3876 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003877 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3878 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3879 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003880 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003881 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003882 goto out;
3883 }
3884 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003885 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3886 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3887 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003888 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003889 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003890 goto out;
3891 }
3892 }
3893
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003894 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003895 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003896
Emeric Brunb982a3d2010-01-04 15:45:53 +01003897 if (strcmp(args[myidx], "table") == 0) {
3898 myidx++;
3899 name = args[myidx++];
3900 }
3901
Willy Tarreauef6494c2010-01-28 17:12:36 +01003902 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003903 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3904 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3905 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003906 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003907 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003908 goto out;
3909 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003910 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003911 else if (*(args[myidx])) {
3912 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3913 file, linenum, args[0], args[myidx]);
3914 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003915 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003916 goto out;
3917 }
Emeric Brun97679e72010-09-23 17:56:44 +02003918 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003919 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003920 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003921 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003922
Emeric Brunb982a3d2010-01-04 15:45:53 +01003923 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3924 rule->cond = cond;
3925 rule->expr = expr;
3926 rule->flags = flags;
3927 rule->table.name = name ? strdup(name) : NULL;
3928 LIST_INIT(&rule->list);
3929 if (flags & STK_ON_RSP)
3930 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3931 else
3932 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3933 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003934 else if (!strcmp(args[0], "stats")) {
3935 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3936 curproxy->uri_auth = NULL; /* we must detach from the default config */
3937
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003938 if (!*args[1]) {
3939 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003940 } else if (!strcmp(args[1], "admin")) {
3941 struct stats_admin_rule *rule;
3942
3943 if (curproxy == &defproxy) {
3944 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
3947 }
3948
3949 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3950 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3951 err_code |= ERR_ALERT | ERR_ABORT;
3952 goto out;
3953 }
3954
3955 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3956 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3957 file, linenum, args[0], args[1]);
3958 err_code |= ERR_ALERT | ERR_FATAL;
3959 goto out;
3960 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003961 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3962 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3963 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003964 err_code |= ERR_ALERT | ERR_FATAL;
3965 goto out;
3966 }
3967
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003968 err_code |= warnif_cond_conflicts(cond,
3969 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3970 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003971
3972 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3973 rule->cond = cond;
3974 LIST_INIT(&rule->list);
3975 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976 } else if (!strcmp(args[1], "uri")) {
3977 if (*(args[2]) == 0) {
3978 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003981 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3982 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003983 err_code |= ERR_ALERT | ERR_ABORT;
3984 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003985 }
3986 } else if (!strcmp(args[1], "realm")) {
3987 if (*(args[2]) == 0) {
3988 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003989 err_code |= ERR_ALERT | ERR_FATAL;
3990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003991 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3992 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003993 err_code |= ERR_ALERT | ERR_ABORT;
3994 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003995 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003996 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003997 unsigned interval;
3998
3999 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4000 if (err) {
4001 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4002 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004003 err_code |= ERR_ALERT | ERR_FATAL;
4004 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004005 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4006 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004007 err_code |= ERR_ALERT | ERR_ABORT;
4008 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004009 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004010 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01004011 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004012
4013 if (curproxy == &defproxy) {
4014 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4015 err_code |= ERR_ALERT | ERR_FATAL;
4016 goto out;
4017 }
4018
4019 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4020 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4021 err_code |= ERR_ALERT | ERR_ABORT;
4022 goto out;
4023 }
4024
Willy Tarreauff011f22011-01-06 17:51:27 +01004025 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
4026 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004027 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4028 file, linenum, args[0]);
4029 err_code |= ERR_WARN;
4030 }
4031
Willy Tarreauff011f22011-01-06 17:51:27 +01004032 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004033
Willy Tarreauff011f22011-01-06 17:51:27 +01004034 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004035 err_code |= ERR_ALERT | ERR_ABORT;
4036 goto out;
4037 }
4038
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004039 err_code |= warnif_cond_conflicts(rule->cond,
4040 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4041 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004042 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004043
Willy Tarreaubaaee002006-06-26 02:48:02 +02004044 } else if (!strcmp(args[1], "auth")) {
4045 if (*(args[2]) == 0) {
4046 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004047 err_code |= ERR_ALERT | ERR_FATAL;
4048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004049 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4050 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004051 err_code |= ERR_ALERT | ERR_ABORT;
4052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004053 }
4054 } else if (!strcmp(args[1], "scope")) {
4055 if (*(args[2]) == 0) {
4056 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004057 err_code |= ERR_ALERT | ERR_FATAL;
4058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004059 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4060 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004061 err_code |= ERR_ALERT | ERR_ABORT;
4062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004063 }
4064 } else if (!strcmp(args[1], "enable")) {
4065 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4066 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004067 err_code |= ERR_ALERT | ERR_ABORT;
4068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004069 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004070 } else if (!strcmp(args[1], "hide-version")) {
4071 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4072 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004073 err_code |= ERR_ALERT | ERR_ABORT;
4074 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004075 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004076 } else if (!strcmp(args[1], "show-legends")) {
4077 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4078 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4079 err_code |= ERR_ALERT | ERR_ABORT;
4080 goto out;
4081 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004082 } else if (!strcmp(args[1], "show-node")) {
4083
4084 if (*args[2]) {
4085 int i;
4086 char c;
4087
4088 for (i=0; args[2][i]; i++) {
4089 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004090 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4091 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004092 break;
4093 }
4094
4095 if (!i || args[2][i]) {
4096 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4097 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4098 file, linenum, args[0], args[1]);
4099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
4101 }
4102 }
4103
4104 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4105 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4106 err_code |= ERR_ALERT | ERR_ABORT;
4107 goto out;
4108 }
4109 } else if (!strcmp(args[1], "show-desc")) {
4110 char *desc = NULL;
4111
4112 if (*args[2]) {
4113 int i, len=0;
4114 char *d;
4115
Willy Tarreau348acfe2014-04-14 15:00:39 +02004116 for (i = 2; *args[i]; i++)
4117 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004118
4119 desc = d = (char *)calloc(1, len);
4120
Willy Tarreau348acfe2014-04-14 15:00:39 +02004121 d += snprintf(d, desc + len - d, "%s", args[2]);
4122 for (i = 3; *args[i]; i++)
4123 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004124 }
4125
4126 if (!*args[2] && !global.desc)
4127 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4128 file, linenum, args[1]);
4129 else {
4130 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4131 free(desc);
4132 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4133 err_code |= ERR_ALERT | ERR_ABORT;
4134 goto out;
4135 }
4136 free(desc);
4137 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004138 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004139stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004140 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 +01004141 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004142 err_code |= ERR_ALERT | ERR_FATAL;
4143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004144 }
4145 }
4146 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004147 int optnum;
4148
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004149 if (*(args[1]) == '\0') {
4150 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4151 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004152 err_code |= ERR_ALERT | ERR_FATAL;
4153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004155
4156 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4157 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004158 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4159 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4160 file, linenum, cfg_opts[optnum].name);
4161 err_code |= ERR_ALERT | ERR_FATAL;
4162 goto out;
4163 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004164 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4165 goto out;
4166
Willy Tarreau93893792009-07-23 13:19:11 +02004167 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4168 err_code |= ERR_WARN;
4169 goto out;
4170 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004171
Willy Tarreau3842f002009-06-14 11:39:52 +02004172 curproxy->no_options &= ~cfg_opts[optnum].val;
4173 curproxy->options &= ~cfg_opts[optnum].val;
4174
4175 switch (kwm) {
4176 case KWM_STD:
4177 curproxy->options |= cfg_opts[optnum].val;
4178 break;
4179 case KWM_NO:
4180 curproxy->no_options |= cfg_opts[optnum].val;
4181 break;
4182 case KWM_DEF: /* already cleared */
4183 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004184 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004185
Willy Tarreau93893792009-07-23 13:19:11 +02004186 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004187 }
4188 }
4189
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004190 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4191 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004192 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4193 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4194 file, linenum, cfg_opts2[optnum].name);
4195 err_code |= ERR_ALERT | ERR_FATAL;
4196 goto out;
4197 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004198 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4199 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004200 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4201 err_code |= ERR_WARN;
4202 goto out;
4203 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004204
Willy Tarreau3842f002009-06-14 11:39:52 +02004205 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4206 curproxy->options2 &= ~cfg_opts2[optnum].val;
4207
4208 switch (kwm) {
4209 case KWM_STD:
4210 curproxy->options2 |= cfg_opts2[optnum].val;
4211 break;
4212 case KWM_NO:
4213 curproxy->no_options2 |= cfg_opts2[optnum].val;
4214 break;
4215 case KWM_DEF: /* already cleared */
4216 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004217 }
Willy Tarreau93893792009-07-23 13:19:11 +02004218 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004219 }
4220 }
4221
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004222 /* HTTP options override each other. They can be cancelled using
4223 * "no option xxx" which only switches to default mode if the mode
4224 * was this one (useful for cancelling options set in defaults
4225 * sections).
4226 */
4227 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004228 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4229 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004230 if (kwm == KWM_STD) {
4231 curproxy->options &= ~PR_O_HTTP_MODE;
4232 curproxy->options |= PR_O_HTTP_PCL;
4233 goto out;
4234 }
4235 else if (kwm == KWM_NO) {
4236 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4237 curproxy->options &= ~PR_O_HTTP_MODE;
4238 goto out;
4239 }
4240 }
4241 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004242 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4243 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004244 if (kwm == KWM_STD) {
4245 curproxy->options &= ~PR_O_HTTP_MODE;
4246 curproxy->options |= PR_O_HTTP_FCL;
4247 goto out;
4248 }
4249 else if (kwm == KWM_NO) {
4250 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4251 curproxy->options &= ~PR_O_HTTP_MODE;
4252 goto out;
4253 }
4254 }
4255 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004256 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4257 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004258 if (kwm == KWM_STD) {
4259 curproxy->options &= ~PR_O_HTTP_MODE;
4260 curproxy->options |= PR_O_HTTP_SCL;
4261 goto out;
4262 }
4263 else if (kwm == KWM_NO) {
4264 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4265 curproxy->options &= ~PR_O_HTTP_MODE;
4266 goto out;
4267 }
4268 }
4269 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004270 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4271 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004272 if (kwm == KWM_STD) {
4273 curproxy->options &= ~PR_O_HTTP_MODE;
4274 curproxy->options |= PR_O_HTTP_KAL;
4275 goto out;
4276 }
4277 else if (kwm == KWM_NO) {
4278 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4279 curproxy->options &= ~PR_O_HTTP_MODE;
4280 goto out;
4281 }
4282 }
4283 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004284 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4285 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004286 if (kwm == KWM_STD) {
4287 curproxy->options &= ~PR_O_HTTP_MODE;
4288 curproxy->options |= PR_O_HTTP_TUN;
4289 goto out;
4290 }
4291 else if (kwm == KWM_NO) {
4292 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4293 curproxy->options &= ~PR_O_HTTP_MODE;
4294 goto out;
4295 }
4296 }
4297
Joseph Lynch726ab712015-05-11 23:25:34 -07004298 /* Redispatch can take an integer argument that control when the
4299 * resispatch occurs. All values are relative to the retries option.
4300 * This can be cancelled using "no option xxx".
4301 */
4302 if (strcmp(args[1], "redispatch") == 0) {
4303 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4304 err_code |= ERR_WARN;
4305 goto out;
4306 }
4307
4308 curproxy->no_options &= ~PR_O_REDISP;
4309 curproxy->options &= ~PR_O_REDISP;
4310
4311 switch (kwm) {
4312 case KWM_STD:
4313 curproxy->options |= PR_O_REDISP;
4314 curproxy->redispatch_after = -1;
4315 if(*args[2]) {
4316 curproxy->redispatch_after = atol(args[2]);
4317 }
4318 break;
4319 case KWM_NO:
4320 curproxy->no_options |= PR_O_REDISP;
4321 curproxy->redispatch_after = 0;
4322 break;
4323 case KWM_DEF: /* already cleared */
4324 break;
4325 }
4326 goto out;
4327 }
4328
Willy Tarreau3842f002009-06-14 11:39:52 +02004329 if (kwm != KWM_STD) {
4330 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004331 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004332 err_code |= ERR_ALERT | ERR_FATAL;
4333 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004334 }
4335
Emeric Brun3a058f32009-06-30 18:26:00 +02004336 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004337 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004338 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004339 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004340 if (*(args[2]) != '\0') {
4341 if (!strcmp(args[2], "clf")) {
4342 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004343 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004344 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004345 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004346 err_code |= ERR_ALERT | ERR_FATAL;
4347 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004348 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004349 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4350 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004351 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004352 if (curproxy->conf.logformat_string != default_http_log_format &&
4353 curproxy->conf.logformat_string != default_tcp_log_format &&
4354 curproxy->conf.logformat_string != clf_http_log_format)
4355 free(curproxy->conf.logformat_string);
4356 curproxy->conf.logformat_string = logformat;
4357
4358 free(curproxy->conf.lfs_file);
4359 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4360 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004361 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004362 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004363 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004364 if (curproxy->conf.logformat_string != default_http_log_format &&
4365 curproxy->conf.logformat_string != default_tcp_log_format &&
4366 curproxy->conf.logformat_string != clf_http_log_format)
4367 free(curproxy->conf.logformat_string);
4368 curproxy->conf.logformat_string = default_tcp_log_format;
4369
4370 free(curproxy->conf.lfs_file);
4371 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4372 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004373
4374 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4375 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004376 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004377 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004378 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004379 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004380 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004381
William Lallemanddf1425a2015-04-28 20:17:49 +02004382 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4383 goto out;
4384
Willy Tarreau13943ab2006-12-31 00:24:10 +01004385 if (curproxy->cap & PR_CAP_FE)
4386 curproxy->options |= PR_O_TCP_CLI_KA;
4387 if (curproxy->cap & PR_CAP_BE)
4388 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004389 }
4390 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004391 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004392 err_code |= ERR_WARN;
4393
Willy Tarreaubaaee002006-06-26 02:48:02 +02004394 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004395 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004396 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004397 curproxy->options2 &= ~PR_O2_CHK_ANY;
4398 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004399 if (!*args[2]) { /* no argument */
4400 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4401 curproxy->check_len = strlen(DEF_CHECK_REQ);
4402 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004403 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004404 curproxy->check_req = (char *)malloc(reqlen);
4405 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004406 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004407 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004408 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004409 if (*args[4])
4410 reqlen += strlen(args[4]);
4411 else
4412 reqlen += strlen("HTTP/1.0");
4413
4414 curproxy->check_req = (char *)malloc(reqlen);
4415 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004416 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004417 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004418 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4419 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004420 }
4421 else if (!strcmp(args[1], "ssl-hello-chk")) {
4422 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004423 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004424 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004425
Willy Tarreaua534fea2008-08-03 12:19:50 +02004426 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004427 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004428 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004429 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004430
4431 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004433 }
Willy Tarreau23677902007-05-08 23:50:35 +02004434 else if (!strcmp(args[1], "smtpchk")) {
4435 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004436 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004437 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004438 curproxy->options2 &= ~PR_O2_CHK_ANY;
4439 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004440
4441 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4442 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4443 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4444 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4445 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4446 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4447 curproxy->check_req = (char *)malloc(reqlen);
4448 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4449 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4450 } else {
4451 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4452 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4453 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4454 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4455 }
4456 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004457 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4458 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004459 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004460 else if (!strcmp(args[1], "pgsql-check")) {
4461 /* use PostgreSQL request to check servers' health */
4462 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4463 err_code |= ERR_WARN;
4464
4465 free(curproxy->check_req);
4466 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004467 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004468 curproxy->options2 |= PR_O2_PGSQL_CHK;
4469
4470 if (*(args[2])) {
4471 int cur_arg = 2;
4472
4473 while (*(args[cur_arg])) {
4474 if (strcmp(args[cur_arg], "user") == 0) {
4475 char * packet;
4476 uint32_t packet_len;
4477 uint32_t pv;
4478
4479 /* suboption header - needs additional argument for it */
4480 if (*(args[cur_arg+1]) == 0) {
4481 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4482 file, linenum, args[0], args[1], args[cur_arg]);
4483 err_code |= ERR_ALERT | ERR_FATAL;
4484 goto out;
4485 }
4486
4487 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4488 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4489 pv = htonl(0x30000); /* protocol version 3.0 */
4490
4491 packet = (char*) calloc(1, packet_len);
4492
4493 memcpy(packet + 4, &pv, 4);
4494
4495 /* copy "user" */
4496 memcpy(packet + 8, "user", 4);
4497
4498 /* copy username */
4499 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4500
4501 free(curproxy->check_req);
4502 curproxy->check_req = packet;
4503 curproxy->check_len = packet_len;
4504
4505 packet_len = htonl(packet_len);
4506 memcpy(packet, &packet_len, 4);
4507 cur_arg += 2;
4508 } else {
4509 /* unknown suboption - catchall */
4510 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4511 file, linenum, args[0], args[1]);
4512 err_code |= ERR_ALERT | ERR_FATAL;
4513 goto out;
4514 }
4515 } /* end while loop */
4516 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004517 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4518 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004519 }
4520
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004521 else if (!strcmp(args[1], "redis-check")) {
4522 /* use REDIS PING request to check servers' health */
4523 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4524 err_code |= ERR_WARN;
4525
4526 free(curproxy->check_req);
4527 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004528 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004529 curproxy->options2 |= PR_O2_REDIS_CHK;
4530
4531 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4532 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4533 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004534
4535 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4536 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004537 }
4538
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004539 else if (!strcmp(args[1], "mysql-check")) {
4540 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004541 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4542 err_code |= ERR_WARN;
4543
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004544 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004545 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004546 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004547 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004548
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004549 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004550 * const char mysql40_client_auth_pkt[] = {
4551 * "\x0e\x00\x00" // packet length
4552 * "\x01" // packet number
4553 * "\x00\x00" // client capabilities
4554 * "\x00\x00\x01" // max packet
4555 * "haproxy\x00" // username (null terminated string)
4556 * "\x00" // filler (always 0x00)
4557 * "\x01\x00\x00" // packet length
4558 * "\x00" // packet number
4559 * "\x01" // COM_QUIT command
4560 * };
4561 */
4562
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004563 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4564 * const char mysql41_client_auth_pkt[] = {
4565 * "\x0e\x00\x00\" // packet length
4566 * "\x01" // packet number
4567 * "\x00\x00\x00\x00" // client capabilities
4568 * "\x00\x00\x00\x01" // max packet
4569 * "\x21" // character set (UTF-8)
4570 * char[23] // All zeroes
4571 * "haproxy\x00" // username (null terminated string)
4572 * "\x00" // filler (always 0x00)
4573 * "\x01\x00\x00" // packet length
4574 * "\x00" // packet number
4575 * "\x01" // COM_QUIT command
4576 * };
4577 */
4578
4579
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004580 if (*(args[2])) {
4581 int cur_arg = 2;
4582
4583 while (*(args[cur_arg])) {
4584 if (strcmp(args[cur_arg], "user") == 0) {
4585 char *mysqluser;
4586 int packetlen, reqlen, userlen;
4587
4588 /* suboption header - needs additional argument for it */
4589 if (*(args[cur_arg+1]) == 0) {
4590 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4591 file, linenum, args[0], args[1], args[cur_arg]);
4592 err_code |= ERR_ALERT | ERR_FATAL;
4593 goto out;
4594 }
4595 mysqluser = args[cur_arg + 1];
4596 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004597
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004598 if (*(args[cur_arg+2])) {
4599 if (!strcmp(args[cur_arg+2], "post-41")) {
4600 packetlen = userlen + 7 + 27;
4601 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004602
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004603 free(curproxy->check_req);
4604 curproxy->check_req = (char *)calloc(1, reqlen);
4605 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004606
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004607 snprintf(curproxy->check_req, 4, "%c%c%c",
4608 ((unsigned char) packetlen & 0xff),
4609 ((unsigned char) (packetlen >> 8) & 0xff),
4610 ((unsigned char) (packetlen >> 16) & 0xff));
4611
4612 curproxy->check_req[3] = 1;
4613 curproxy->check_req[5] = 130;
4614 curproxy->check_req[11] = 1;
4615 curproxy->check_req[12] = 33;
4616 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4617 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4618 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4619 cur_arg += 3;
4620 } else {
4621 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4622 err_code |= ERR_ALERT | ERR_FATAL;
4623 goto out;
4624 }
4625 } else {
4626 packetlen = userlen + 7;
4627 reqlen = packetlen + 9;
4628
4629 free(curproxy->check_req);
4630 curproxy->check_req = (char *)calloc(1, reqlen);
4631 curproxy->check_len = reqlen;
4632
4633 snprintf(curproxy->check_req, 4, "%c%c%c",
4634 ((unsigned char) packetlen & 0xff),
4635 ((unsigned char) (packetlen >> 8) & 0xff),
4636 ((unsigned char) (packetlen >> 16) & 0xff));
4637
4638 curproxy->check_req[3] = 1;
4639 curproxy->check_req[5] = 128;
4640 curproxy->check_req[8] = 1;
4641 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4642 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4643 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4644 cur_arg += 2;
4645 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004646 } else {
4647 /* unknown suboption - catchall */
4648 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4649 file, linenum, args[0], args[1]);
4650 err_code |= ERR_ALERT | ERR_FATAL;
4651 goto out;
4652 }
4653 } /* end while loop */
4654 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004655 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004656 else if (!strcmp(args[1], "ldap-check")) {
4657 /* use LDAP request to check servers' health */
4658 free(curproxy->check_req);
4659 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004660 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004661 curproxy->options2 |= PR_O2_LDAP_CHK;
4662
4663 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4664 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4665 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004666 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4667 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004668 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004669 else if (!strcmp(args[1], "tcp-check")) {
4670 /* use raw TCPCHK send/expect to check servers' health */
4671 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4672 err_code |= ERR_WARN;
4673
4674 free(curproxy->check_req);
4675 curproxy->check_req = NULL;
4676 curproxy->options2 &= ~PR_O2_CHK_ANY;
4677 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004678 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4679 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004680 }
Simon Horman98637e52014-06-20 12:30:16 +09004681 else if (!strcmp(args[1], "external-check")) {
4682 /* excute an external command to check servers' health */
4683 free(curproxy->check_req);
4684 curproxy->check_req = NULL;
4685 curproxy->options2 &= ~PR_O2_CHK_ANY;
4686 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004687 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4688 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004689 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004690 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004691 int cur_arg;
4692
4693 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4694 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004695 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004696
Willy Tarreau87cf5142011-08-19 22:57:24 +02004697 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004698
4699 free(curproxy->fwdfor_hdr_name);
4700 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4701 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4702
4703 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4704 cur_arg = 2;
4705 while (*(args[cur_arg])) {
4706 if (!strcmp(args[cur_arg], "except")) {
4707 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004708 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004709 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4710 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004711 err_code |= ERR_ALERT | ERR_FATAL;
4712 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004713 }
4714 /* flush useless bits */
4715 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004716 cur_arg += 2;
4717 } else if (!strcmp(args[cur_arg], "header")) {
4718 /* suboption header - needs additional argument for it */
4719 if (*(args[cur_arg+1]) == 0) {
4720 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4721 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004722 err_code |= ERR_ALERT | ERR_FATAL;
4723 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004724 }
4725 free(curproxy->fwdfor_hdr_name);
4726 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4727 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4728 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004729 } else if (!strcmp(args[cur_arg], "if-none")) {
4730 curproxy->options &= ~PR_O_FF_ALWAYS;
4731 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004732 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004733 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004734 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004735 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004736 err_code |= ERR_ALERT | ERR_FATAL;
4737 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004738 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004739 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004740 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004741 else if (!strcmp(args[1], "originalto")) {
4742 int cur_arg;
4743
4744 /* insert x-original-to field, but not for the IP address listed as an except.
4745 * set default options (ie: bitfield, header name, etc)
4746 */
4747
4748 curproxy->options |= PR_O_ORGTO;
4749
4750 free(curproxy->orgto_hdr_name);
4751 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4752 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4753
Willy Tarreau87cf5142011-08-19 22:57:24 +02004754 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004755 cur_arg = 2;
4756 while (*(args[cur_arg])) {
4757 if (!strcmp(args[cur_arg], "except")) {
4758 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004759 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 +02004760 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4761 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004762 err_code |= ERR_ALERT | ERR_FATAL;
4763 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004764 }
4765 /* flush useless bits */
4766 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4767 cur_arg += 2;
4768 } else if (!strcmp(args[cur_arg], "header")) {
4769 /* suboption header - needs additional argument for it */
4770 if (*(args[cur_arg+1]) == 0) {
4771 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4772 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004773 err_code |= ERR_ALERT | ERR_FATAL;
4774 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004775 }
4776 free(curproxy->orgto_hdr_name);
4777 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4778 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4779 cur_arg += 2;
4780 } else {
4781 /* unknown suboption - catchall */
4782 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4783 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004784 err_code |= ERR_ALERT | ERR_FATAL;
4785 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004786 }
4787 } /* end while loop */
4788 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004789 else {
4790 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004791 err_code |= ERR_ALERT | ERR_FATAL;
4792 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004793 }
Willy Tarreau93893792009-07-23 13:19:11 +02004794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004795 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004796 else if (!strcmp(args[0], "default_backend")) {
4797 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004798 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004799
4800 if (*(args[1]) == 0) {
4801 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004802 err_code |= ERR_ALERT | ERR_FATAL;
4803 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004804 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004805 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004806 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02004807
4808 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
4809 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004810 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004811 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004812 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004813 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004814
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004815 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4816 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 +01004817 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004818 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004819 /* enable reconnections to dispatch */
4820 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02004821
4822 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
4823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004824 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004825 else if (!strcmp(args[0], "http-check")) {
4826 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004827 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004828
4829 if (strcmp(args[1], "disable-on-404") == 0) {
4830 /* enable a graceful server shutdown on an HTTP 404 response */
4831 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02004832 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4833 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004834 }
Willy Tarreauef781042010-01-27 11:53:01 +01004835 else if (strcmp(args[1], "send-state") == 0) {
4836 /* enable emission of the apparent state of a server in HTTP checks */
4837 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02004838 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4839 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01004840 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004841 else if (strcmp(args[1], "expect") == 0) {
4842 const char *ptr_arg;
4843 int cur_arg;
4844
4845 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4846 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4847 err_code |= ERR_ALERT | ERR_FATAL;
4848 goto out;
4849 }
4850
4851 cur_arg = 2;
4852 /* consider exclamation marks, sole or at the beginning of a word */
4853 while (*(ptr_arg = args[cur_arg])) {
4854 while (*ptr_arg == '!') {
4855 curproxy->options2 ^= PR_O2_EXP_INV;
4856 ptr_arg++;
4857 }
4858 if (*ptr_arg)
4859 break;
4860 cur_arg++;
4861 }
4862 /* now ptr_arg points to the beginning of a word past any possible
4863 * exclamation mark, and cur_arg is the argument which holds this word.
4864 */
4865 if (strcmp(ptr_arg, "status") == 0) {
4866 if (!*(args[cur_arg + 1])) {
4867 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4868 file, linenum, args[0], args[1], ptr_arg);
4869 err_code |= ERR_ALERT | ERR_FATAL;
4870 goto out;
4871 }
4872 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004873 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004874 curproxy->expect_str = strdup(args[cur_arg + 1]);
4875 }
4876 else if (strcmp(ptr_arg, "string") == 0) {
4877 if (!*(args[cur_arg + 1])) {
4878 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4879 file, linenum, args[0], args[1], ptr_arg);
4880 err_code |= ERR_ALERT | ERR_FATAL;
4881 goto out;
4882 }
4883 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004884 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004885 curproxy->expect_str = strdup(args[cur_arg + 1]);
4886 }
4887 else if (strcmp(ptr_arg, "rstatus") == 0) {
4888 if (!*(args[cur_arg + 1])) {
4889 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4890 file, linenum, args[0], args[1], ptr_arg);
4891 err_code |= ERR_ALERT | ERR_FATAL;
4892 goto out;
4893 }
4894 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004895 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004896 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004897 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004898 free(curproxy->expect_regex);
4899 curproxy->expect_regex = NULL;
4900 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004901 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004902 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4903 error = NULL;
4904 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4905 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4906 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4907 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004908 err_code |= ERR_ALERT | ERR_FATAL;
4909 goto out;
4910 }
4911 }
4912 else if (strcmp(ptr_arg, "rstring") == 0) {
4913 if (!*(args[cur_arg + 1])) {
4914 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4915 file, linenum, args[0], args[1], ptr_arg);
4916 err_code |= ERR_ALERT | ERR_FATAL;
4917 goto out;
4918 }
4919 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004920 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004921 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004922 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004923 free(curproxy->expect_regex);
4924 curproxy->expect_regex = NULL;
4925 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004926 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004927 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4928 error = NULL;
4929 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4930 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4931 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4932 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004933 err_code |= ERR_ALERT | ERR_FATAL;
4934 goto out;
4935 }
4936 }
4937 else {
4938 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4939 file, linenum, args[0], args[1], ptr_arg);
4940 err_code |= ERR_ALERT | ERR_FATAL;
4941 goto out;
4942 }
4943 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004944 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004945 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 +02004946 err_code |= ERR_ALERT | ERR_FATAL;
4947 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004948 }
4949 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004950 else if (!strcmp(args[0], "tcp-check")) {
4951 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4952 err_code |= ERR_WARN;
4953
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004954 if (strcmp(args[1], "comment") == 0) {
4955 int cur_arg;
4956 struct tcpcheck_rule *tcpcheck;
4957
4958 cur_arg = 1;
4959 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4960 tcpcheck->action = TCPCHK_ACT_COMMENT;
4961
4962 if (!*args[cur_arg + 1]) {
4963 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4964 file, linenum, args[cur_arg]);
4965 err_code |= ERR_ALERT | ERR_FATAL;
4966 goto out;
4967 }
4968
4969 tcpcheck->comment = strdup(args[cur_arg + 1]);
4970
4971 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02004972 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4973 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004974 }
4975 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004976 const char *ptr_arg;
4977 int cur_arg;
4978 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004979
4980 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02004981 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
4982 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
4983 tcpcheck->action == TCPCHK_ACT_COMMENT) {
4984 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
4985 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004986
Willy Tarreau5581c272015-05-13 12:24:53 +02004987 if (&tcpcheck->list != &curproxy->tcpcheck_rules
4988 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4989 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4990 file, linenum);
4991 err_code |= ERR_ALERT | ERR_FATAL;
4992 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004993 }
4994
4995 cur_arg = 2;
4996 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4997 tcpcheck->action = TCPCHK_ACT_CONNECT;
4998
4999 /* parsing each parameters to fill up the rule */
5000 while (*(ptr_arg = args[cur_arg])) {
5001 /* tcp port */
5002 if (strcmp(args[cur_arg], "port") == 0) {
5003 if ( (atol(args[cur_arg + 1]) > 65535) ||
5004 (atol(args[cur_arg + 1]) < 1) ){
5005 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5006 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5007 err_code |= ERR_ALERT | ERR_FATAL;
5008 goto out;
5009 }
5010 tcpcheck->port = atol(args[cur_arg + 1]);
5011 cur_arg += 2;
5012 }
5013 /* send proxy protocol */
5014 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5015 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5016 cur_arg++;
5017 }
5018#ifdef USE_OPENSSL
5019 else if (strcmp(args[cur_arg], "ssl") == 0) {
5020 curproxy->options |= PR_O_TCPCHK_SSL;
5021 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5022 cur_arg++;
5023 }
5024#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005025 /* comment for this tcpcheck line */
5026 else if (strcmp(args[cur_arg], "comment") == 0) {
5027 if (!*args[cur_arg + 1]) {
5028 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5029 file, linenum, args[cur_arg]);
5030 err_code |= ERR_ALERT | ERR_FATAL;
5031 goto out;
5032 }
5033 tcpcheck->comment = strdup(args[cur_arg + 1]);
5034 cur_arg += 2;
5035 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005036 else {
5037#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005038 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 +01005039#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005040 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 +01005041#endif /* USE_OPENSSL */
5042 file, linenum, args[0], args[1], args[cur_arg]);
5043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
5045 }
5046
5047 }
5048
5049 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5050 }
5051 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005052 if (! *(args[2]) ) {
5053 /* SEND string expected */
5054 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5055 file, linenum, args[0], args[1], args[2]);
5056 err_code |= ERR_ALERT | ERR_FATAL;
5057 goto out;
5058 } else {
5059 struct tcpcheck_rule *tcpcheck;
5060
5061 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5062
5063 tcpcheck->action = TCPCHK_ACT_SEND;
5064 tcpcheck->string_len = strlen(args[2]);
5065 tcpcheck->string = strdup(args[2]);
5066 tcpcheck->expect_regex = NULL;
5067
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005068 /* comment for this tcpcheck line */
5069 if (strcmp(args[3], "comment") == 0) {
5070 if (!*args[4]) {
5071 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5072 file, linenum, args[3]);
5073 err_code |= ERR_ALERT | ERR_FATAL;
5074 goto out;
5075 }
5076 tcpcheck->comment = strdup(args[4]);
5077 }
5078
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005079 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5080 }
5081 }
5082 else if (strcmp(args[1], "send-binary") == 0) {
5083 if (! *(args[2]) ) {
5084 /* SEND binary string expected */
5085 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5086 file, linenum, args[0], args[1], args[2]);
5087 err_code |= ERR_ALERT | ERR_FATAL;
5088 goto out;
5089 } else {
5090 struct tcpcheck_rule *tcpcheck;
5091 char *err = NULL;
5092
5093 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5094
5095 tcpcheck->action = TCPCHK_ACT_SEND;
5096 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5097 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5098 file, linenum, args[0], args[1], args[2], err);
5099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
5101 }
5102 tcpcheck->expect_regex = NULL;
5103
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005104 /* comment for this tcpcheck line */
5105 if (strcmp(args[3], "comment") == 0) {
5106 if (!*args[4]) {
5107 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5108 file, linenum, args[3]);
5109 err_code |= ERR_ALERT | ERR_FATAL;
5110 goto out;
5111 }
5112 tcpcheck->comment = strdup(args[4]);
5113 }
5114
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005115 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5116 }
5117 }
5118 else if (strcmp(args[1], "expect") == 0) {
5119 const char *ptr_arg;
5120 int cur_arg;
5121 int inverse = 0;
5122
5123 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5124 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5125 err_code |= ERR_ALERT | ERR_FATAL;
5126 goto out;
5127 }
5128
5129 cur_arg = 2;
5130 /* consider exclamation marks, sole or at the beginning of a word */
5131 while (*(ptr_arg = args[cur_arg])) {
5132 while (*ptr_arg == '!') {
5133 inverse = !inverse;
5134 ptr_arg++;
5135 }
5136 if (*ptr_arg)
5137 break;
5138 cur_arg++;
5139 }
5140 /* now ptr_arg points to the beginning of a word past any possible
5141 * exclamation mark, and cur_arg is the argument which holds this word.
5142 */
5143 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005144 struct tcpcheck_rule *tcpcheck;
5145 char *err = NULL;
5146
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005147 if (!*(args[cur_arg + 1])) {
5148 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5149 file, linenum, args[0], args[1], ptr_arg);
5150 err_code |= ERR_ALERT | ERR_FATAL;
5151 goto out;
5152 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005153
5154 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5155
5156 tcpcheck->action = TCPCHK_ACT_EXPECT;
5157 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5158 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5159 file, linenum, args[0], args[1], args[2], err);
5160 err_code |= ERR_ALERT | ERR_FATAL;
5161 goto out;
5162 }
5163 tcpcheck->expect_regex = NULL;
5164 tcpcheck->inverse = inverse;
5165
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005166 /* tcpcheck comment */
5167 cur_arg += 2;
5168 if (strcmp(args[cur_arg], "comment") == 0) {
5169 if (!*args[cur_arg + 1]) {
5170 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5171 file, linenum, args[cur_arg + 1]);
5172 err_code |= ERR_ALERT | ERR_FATAL;
5173 goto out;
5174 }
5175 tcpcheck->comment = strdup(args[cur_arg + 1]);
5176 }
5177
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005178 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5179 }
5180 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005181 struct tcpcheck_rule *tcpcheck;
5182
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005183 if (!*(args[cur_arg + 1])) {
5184 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5185 file, linenum, args[0], args[1], ptr_arg);
5186 err_code |= ERR_ALERT | ERR_FATAL;
5187 goto out;
5188 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005189
5190 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5191
5192 tcpcheck->action = TCPCHK_ACT_EXPECT;
5193 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5194 tcpcheck->string = strdup(args[cur_arg + 1]);
5195 tcpcheck->expect_regex = NULL;
5196 tcpcheck->inverse = inverse;
5197
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005198 /* tcpcheck comment */
5199 cur_arg += 2;
5200 if (strcmp(args[cur_arg], "comment") == 0) {
5201 if (!*args[cur_arg + 1]) {
5202 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5203 file, linenum, args[cur_arg + 1]);
5204 err_code |= ERR_ALERT | ERR_FATAL;
5205 goto out;
5206 }
5207 tcpcheck->comment = strdup(args[cur_arg + 1]);
5208 }
5209
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005210 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5211 }
5212 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005213 struct tcpcheck_rule *tcpcheck;
5214
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005215 if (!*(args[cur_arg + 1])) {
5216 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5217 file, linenum, args[0], args[1], ptr_arg);
5218 err_code |= ERR_ALERT | ERR_FATAL;
5219 goto out;
5220 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005221
5222 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5223
5224 tcpcheck->action = TCPCHK_ACT_EXPECT;
5225 tcpcheck->string_len = 0;
5226 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005227 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5228 error = NULL;
5229 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5230 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5231 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5232 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005233 err_code |= ERR_ALERT | ERR_FATAL;
5234 goto out;
5235 }
5236 tcpcheck->inverse = inverse;
5237
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005238 /* tcpcheck comment */
5239 cur_arg += 2;
5240 if (strcmp(args[cur_arg], "comment") == 0) {
5241 if (!*args[cur_arg + 1]) {
5242 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5243 file, linenum, args[cur_arg + 1]);
5244 err_code |= ERR_ALERT | ERR_FATAL;
5245 goto out;
5246 }
5247 tcpcheck->comment = strdup(args[cur_arg + 1]);
5248 }
5249
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005250 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5251 }
5252 else {
5253 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5254 file, linenum, args[0], args[1], ptr_arg);
5255 err_code |= ERR_ALERT | ERR_FATAL;
5256 goto out;
5257 }
5258 }
5259 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005260 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005261 err_code |= ERR_ALERT | ERR_FATAL;
5262 goto out;
5263 }
5264 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005265 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005266 if (curproxy == &defproxy) {
5267 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005268 err_code |= ERR_ALERT | ERR_FATAL;
5269 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005270 }
5271
Willy Tarreaub80c2302007-11-30 20:51:32 +01005272 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005273 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005274
5275 if (strcmp(args[1], "fail") == 0) {
5276 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005277 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005278 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5279 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005280 err_code |= ERR_ALERT | ERR_FATAL;
5281 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005282 }
5283
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005284 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5285 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5286 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005287 err_code |= ERR_ALERT | ERR_FATAL;
5288 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005289 }
5290 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5291 }
5292 else {
5293 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005294 err_code |= ERR_ALERT | ERR_FATAL;
5295 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005296 }
5297 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005298#ifdef TPROXY
5299 else if (!strcmp(args[0], "transparent")) {
5300 /* enable transparent proxy connections */
5301 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005302 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 }
5305#endif
5306 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005307 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005308 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005309
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310 if (*(args[1]) == 0) {
5311 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005312 err_code |= ERR_ALERT | ERR_FATAL;
5313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005314 }
5315 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005316 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005318 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005319 else if (!strcmp(args[0], "backlog")) { /* backlog */
5320 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005321 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005322
5323 if (*(args[1]) == 0) {
5324 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005325 err_code |= ERR_ALERT | ERR_FATAL;
5326 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005327 }
5328 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005329 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5330 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005331 }
Willy Tarreau86034312006-12-29 00:10:33 +01005332 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005333 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005334 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005335
Willy Tarreau86034312006-12-29 00:10:33 +01005336 if (*(args[1]) == 0) {
5337 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005338 err_code |= ERR_ALERT | ERR_FATAL;
5339 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005340 }
5341 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005342 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5343 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005344 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005345 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5346 if (*(args[1]) == 0) {
5347 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005348 err_code |= ERR_ALERT | ERR_FATAL;
5349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005350 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005351 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5352 if (err) {
5353 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5354 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005355 err_code |= ERR_ALERT | ERR_FATAL;
5356 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005357 }
5358 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005359 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005361 }
5362 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005363 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005364 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005365 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005366
Willy Tarreaubaaee002006-06-26 02:48:02 +02005367 if (curproxy == &defproxy) {
5368 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005369 err_code |= ERR_ALERT | ERR_FATAL;
5370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005371 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005372 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005373 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005374
Willy Tarreau902636f2013-03-10 19:44:48 +01005375 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005376 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005377 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005378 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005379 goto out;
5380 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005381
5382 proto = protocol_by_family(sk->ss_family);
5383 if (!proto || !proto->connect) {
5384 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5385 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005386 err_code |= ERR_ALERT | ERR_FATAL;
5387 goto out;
5388 }
5389
5390 if (port1 != port2) {
5391 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5392 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005393 err_code |= ERR_ALERT | ERR_FATAL;
5394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005395 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005396
5397 if (!port1) {
5398 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5399 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005400 err_code |= ERR_ALERT | ERR_FATAL;
5401 goto out;
5402 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005403
William Lallemanddf1425a2015-04-28 20:17:49 +02005404 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5405 goto out;
5406
Willy Tarreaud5191e72010-02-09 20:50:45 +01005407 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005408 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005409 }
5410 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005411 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005412 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005413
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005414 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5415 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005416 err_code |= ERR_ALERT | ERR_FATAL;
5417 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005418 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005419 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005420 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005421 /**
5422 * The syntax for hash-type config element is
5423 * hash-type {map-based|consistent} [[<algo>] avalanche]
5424 *
5425 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5426 */
5427 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005428
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005429 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5430 err_code |= ERR_WARN;
5431
5432 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005433 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5434 }
5435 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005436 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5437 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005438 else if (strcmp(args[1], "avalanche") == 0) {
5439 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]);
5440 err_code |= ERR_ALERT | ERR_FATAL;
5441 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005442 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005443 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005444 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005445 err_code |= ERR_ALERT | ERR_FATAL;
5446 goto out;
5447 }
Bhaskar98634f02013-10-29 23:30:51 -04005448
5449 /* set the hash function to use */
5450 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005451 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005452 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005453
5454 /* if consistent with no argument, then avalanche modifier is also applied */
5455 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5456 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005457 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005458 /* set the hash function */
5459 if (!strcmp(args[2], "sdbm")) {
5460 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5461 }
5462 else if (!strcmp(args[2], "djb2")) {
5463 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005464 }
5465 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005466 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005467 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005468 else if (!strcmp(args[2], "crc32")) {
5469 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5470 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005471 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005472 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 -05005473 err_code |= ERR_ALERT | ERR_FATAL;
5474 goto out;
5475 }
5476
5477 /* set the hash modifier */
5478 if (!strcmp(args[3], "avalanche")) {
5479 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5480 }
5481 else if (*args[3]) {
5482 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5483 err_code |= ERR_ALERT | ERR_FATAL;
5484 goto out;
5485 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005486 }
William Lallemanda73203e2012-03-12 12:48:57 +01005487 }
William Lallemanda73203e2012-03-12 12:48:57 +01005488 else if (strcmp(args[0], "unique-id-format") == 0) {
5489 if (!*(args[1])) {
5490 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5491 err_code |= ERR_ALERT | ERR_FATAL;
5492 goto out;
5493 }
William Lallemand3203ff42012-11-11 17:30:56 +01005494 if (*(args[2])) {
5495 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5496 err_code |= ERR_ALERT | ERR_FATAL;
5497 goto out;
5498 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005499 free(curproxy->conf.uniqueid_format_string);
5500 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005501
Willy Tarreau62a61232013-04-12 18:13:46 +02005502 free(curproxy->conf.uif_file);
5503 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5504 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005505 }
William Lallemanda73203e2012-03-12 12:48:57 +01005506
5507 else if (strcmp(args[0], "unique-id-header") == 0) {
5508 if (!*(args[1])) {
5509 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5510 err_code |= ERR_ALERT | ERR_FATAL;
5511 goto out;
5512 }
5513 free(curproxy->header_unique_id);
5514 curproxy->header_unique_id = strdup(args[1]);
5515 }
5516
William Lallemand723b73a2012-02-08 16:37:49 +01005517 else if (strcmp(args[0], "log-format") == 0) {
5518 if (!*(args[1])) {
5519 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5520 err_code |= ERR_ALERT | ERR_FATAL;
5521 goto out;
5522 }
William Lallemand3203ff42012-11-11 17:30:56 +01005523 if (*(args[2])) {
5524 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5525 err_code |= ERR_ALERT | ERR_FATAL;
5526 goto out;
5527 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005528
Willy Tarreau62a61232013-04-12 18:13:46 +02005529 if (curproxy->conf.logformat_string != default_http_log_format &&
5530 curproxy->conf.logformat_string != default_tcp_log_format &&
5531 curproxy->conf.logformat_string != clf_http_log_format)
5532 free(curproxy->conf.logformat_string);
5533 curproxy->conf.logformat_string = strdup(args[1]);
5534
5535 free(curproxy->conf.lfs_file);
5536 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5537 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005538
5539 /* get a chance to improve log-format error reporting by
5540 * reporting the correct line-number when possible.
5541 */
5542 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5543 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5544 file, linenum, curproxy->id);
5545 err_code |= ERR_WARN;
5546 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005547 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005548 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5549 if (*(args[1]) == 0) {
5550 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5551 err_code |= ERR_ALERT | ERR_FATAL;
5552 goto out;
5553 }
5554 free(curproxy->log_tag);
5555 curproxy->log_tag = strdup(args[1]);
5556 }
William Lallemand0f99e342011-10-12 17:50:54 +02005557 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5558 /* delete previous herited or defined syslog servers */
5559 struct logsrv *back;
5560
5561 if (*(args[1]) != 0) {
5562 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5563 err_code |= ERR_ALERT | ERR_FATAL;
5564 goto out;
5565 }
5566
William Lallemand723b73a2012-02-08 16:37:49 +01005567 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5568 LIST_DEL(&tmplogsrv->list);
5569 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005570 }
5571 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005572 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005573 struct logsrv *logsrv;
5574
Willy Tarreaubaaee002006-06-26 02:48:02 +02005575 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005576 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005577 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005578 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005579 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005580 LIST_INIT(&node->list);
5581 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5582 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005583 }
5584 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005585 struct sockaddr_storage *sk;
5586 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005587 int arg = 0;
5588 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005589
5590 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005591
Willy Tarreau18324f52014-06-27 18:10:07 +02005592 /* just after the address, a length may be specified */
5593 if (strcmp(args[arg+2], "len") == 0) {
5594 len = atoi(args[arg+3]);
5595 if (len < 80 || len > 65535) {
5596 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5597 file, linenum, args[arg+3]);
5598 err_code |= ERR_ALERT | ERR_FATAL;
5599 goto out;
5600 }
5601 logsrv->maxlen = len;
5602
5603 /* skip these two args */
5604 arg += 2;
5605 }
5606 else
5607 logsrv->maxlen = MAX_SYSLOG_LEN;
5608
5609 if (logsrv->maxlen > global.max_syslog_len) {
5610 global.max_syslog_len = logsrv->maxlen;
5611 logline = realloc(logline, global.max_syslog_len + 1);
5612 }
5613
William Lallemanddf1425a2015-04-28 20:17:49 +02005614 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5615 goto out;
5616
Willy Tarreau18324f52014-06-27 18:10:07 +02005617 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005618 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005619 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005620 err_code |= ERR_ALERT | ERR_FATAL;
5621 goto out;
5622
Willy Tarreaubaaee002006-06-26 02:48:02 +02005623 }
5624
William Lallemand0f99e342011-10-12 17:50:54 +02005625 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005626 if (*(args[arg+3])) {
5627 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005628 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005629 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005630 err_code |= ERR_ALERT | ERR_FATAL;
5631 goto out;
5632
Willy Tarreaubaaee002006-06-26 02:48:02 +02005633 }
5634 }
5635
William Lallemand0f99e342011-10-12 17:50:54 +02005636 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005637 if (*(args[arg+4])) {
5638 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005639 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005640 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005641 err_code |= ERR_ALERT | ERR_FATAL;
5642 goto out;
5643
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005644 }
5645 }
5646
Willy Tarreau902636f2013-03-10 19:44:48 +01005647 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005648 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005649 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005650 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005651 goto out;
5652 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005653
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005654 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005655
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005656 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005657 if (port1 != port2) {
5658 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5659 file, linenum, args[0], args[1]);
5660 err_code |= ERR_ALERT | ERR_FATAL;
5661 goto out;
5662 }
5663
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005664 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005665 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005666 }
William Lallemand0f99e342011-10-12 17:50:54 +02005667
5668 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005669 }
5670 else {
5671 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5672 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005673 err_code |= ERR_ALERT | ERR_FATAL;
5674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005675 }
5676 }
5677 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005678 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005679 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005680 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005681 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005682
Willy Tarreau977b8e42006-12-29 14:19:17 +01005683 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005684 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005685
Willy Tarreaubaaee002006-06-26 02:48:02 +02005686 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005687 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5688 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005689 err_code |= ERR_ALERT | ERR_FATAL;
5690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005691 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005692
5693 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005694 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5695 free(curproxy->conn_src.iface_name);
5696 curproxy->conn_src.iface_name = NULL;
5697 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005698
Willy Tarreau902636f2013-03-10 19:44:48 +01005699 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005700 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005701 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005702 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005703 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005704 goto out;
5705 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005706
5707 proto = protocol_by_family(sk->ss_family);
5708 if (!proto || !proto->connect) {
5709 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005710 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005711 err_code |= ERR_ALERT | ERR_FATAL;
5712 goto out;
5713 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005714
5715 if (port1 != port2) {
5716 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5717 file, linenum, args[0], args[1]);
5718 err_code |= ERR_ALERT | ERR_FATAL;
5719 goto out;
5720 }
5721
Willy Tarreauef9a3602012-12-08 22:29:20 +01005722 curproxy->conn_src.source_addr = *sk;
5723 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005724
5725 cur_arg = 2;
5726 while (*(args[cur_arg])) {
5727 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005728#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5729#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005730 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005731 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5732 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005733 err_code |= ERR_ALERT | ERR_FATAL;
5734 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005735 }
5736#endif
5737 if (!*args[cur_arg + 1]) {
5738 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5739 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005740 err_code |= ERR_ALERT | ERR_FATAL;
5741 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005742 }
5743
5744 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005745 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5746 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005747 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005748 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5749 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005750 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5751 char *name, *end;
5752
5753 name = args[cur_arg+1] + 7;
5754 while (isspace(*name))
5755 name++;
5756
5757 end = name;
5758 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5759 end++;
5760
Willy Tarreauef9a3602012-12-08 22:29:20 +01005761 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5762 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5763 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5764 curproxy->conn_src.bind_hdr_len = end - name;
5765 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5766 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5767 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005768
5769 /* now look for an occurrence number */
5770 while (isspace(*end))
5771 end++;
5772 if (*end == ',') {
5773 end++;
5774 name = end;
5775 if (*end == '-')
5776 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005777 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005778 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005779 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005780 }
5781
Willy Tarreauef9a3602012-12-08 22:29:20 +01005782 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005783 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5784 " occurrences values smaller than %d.\n",
5785 file, linenum, MAX_HDR_HISTORY);
5786 err_code |= ERR_ALERT | ERR_FATAL;
5787 goto out;
5788 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005789 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005790 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005791
Willy Tarreau902636f2013-03-10 19:44:48 +01005792 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005793 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005794 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005795 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005796 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005797 goto out;
5798 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005799
5800 proto = protocol_by_family(sk->ss_family);
5801 if (!proto || !proto->connect) {
5802 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5803 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005804 err_code |= ERR_ALERT | ERR_FATAL;
5805 goto out;
5806 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005807
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005808 if (port1 != port2) {
5809 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5810 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005811 err_code |= ERR_ALERT | ERR_FATAL;
5812 goto out;
5813 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005814 curproxy->conn_src.tproxy_addr = *sk;
5815 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005816 }
5817 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005818#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005819 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005820#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005821#else /* no TPROXY support */
5822 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005823 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005824 err_code |= ERR_ALERT | ERR_FATAL;
5825 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005826#endif
5827 cur_arg += 2;
5828 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005829 }
5830
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005831 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5832#ifdef SO_BINDTODEVICE
5833 if (!*args[cur_arg + 1]) {
5834 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5835 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005836 err_code |= ERR_ALERT | ERR_FATAL;
5837 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005838 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005839 free(curproxy->conn_src.iface_name);
5840 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5841 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005842 global.last_checks |= LSTCHK_NETADM;
5843#else
5844 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5845 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005846 err_code |= ERR_ALERT | ERR_FATAL;
5847 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005848#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005849 cur_arg += 2;
5850 continue;
5851 }
5852 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005853 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005854 err_code |= ERR_ALERT | ERR_FATAL;
5855 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005856 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005857 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005858 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5859 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5860 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005861 err_code |= ERR_ALERT | ERR_FATAL;
5862 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005863 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005864 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005865 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005866 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5867 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005868 err_code |= ERR_ALERT | ERR_FATAL;
5869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005870 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005871
5872 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005873 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005874 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005875 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005877 }
5878 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005879 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005880 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005881 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005882 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005884 }
5885 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005886 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005887 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005888 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005889 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 }
5892 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005893 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005894 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005895 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005896 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005897 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005898 }
5899 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005900 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005901 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005902 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005903 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005905 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005906 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005907 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005908 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005909 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005910 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005911 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005912 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005913 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005914 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005915 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5916 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005917 err_code |= ERR_ALERT | ERR_FATAL;
5918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005919 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005920
5921 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005922 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005923 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005924 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005926 }
5927 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005928 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005929 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005930 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005931 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005933 }
5934 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005935 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005936 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005937 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005938 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005939 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005940 }
5941 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005942 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005943 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005944 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005945 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005947 }
5948 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005949 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005950 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005951 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005952 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005953 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005954 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005955 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005956 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005957 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005958 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005959 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005960 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005961 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005962 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005963 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005964
Willy Tarreaubaaee002006-06-26 02:48:02 +02005965 if (curproxy == &defproxy) {
5966 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005967 err_code |= ERR_ALERT | ERR_FATAL;
5968 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005969 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005970 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005971 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005972
Willy Tarreaubaaee002006-06-26 02:48:02 +02005973 if (*(args[1]) == 0) {
5974 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005975 err_code |= ERR_ALERT | ERR_FATAL;
5976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005977 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005978
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005979 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005980 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5981 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5982 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005983 err_code |= ERR_ALERT | ERR_FATAL;
5984 goto out;
5985 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005986 err_code |= warnif_cond_conflicts(cond,
5987 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5988 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005989 }
5990 else if (*args[2]) {
5991 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5992 file, linenum, args[0], args[2]);
5993 err_code |= ERR_ALERT | ERR_FATAL;
5994 goto out;
5995 }
5996
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005997 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005998 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005999 wl->s = strdup(args[1]);
6000 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006001 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006002 }
6003 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006004 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006005 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6006 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006007 err_code |= ERR_ALERT | ERR_FATAL;
6008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006009 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006010
Willy Tarreauade5ec42010-01-28 19:33:49 +01006011 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006012 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006013 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006014 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006016 }
6017 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006018 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006019 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006020 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006021 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006023 }
6024 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006025 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006026 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006027 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006028 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006030 }
6031 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006032 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006033 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6034 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006035 err_code |= ERR_ALERT | ERR_FATAL;
6036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006037 }
6038
Willy Tarreauade5ec42010-01-28 19:33:49 +01006039 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006040 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006041 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006042 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006043 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006044 }
6045 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006046 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006047 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006048 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006049 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006051 }
6052 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006053 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006054 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006055 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006056 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006058 }
6059 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006060 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006061
Willy Tarreaubaaee002006-06-26 02:48:02 +02006062 if (curproxy == &defproxy) {
6063 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006064 err_code |= ERR_ALERT | ERR_FATAL;
6065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006066 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006067 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006068 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006069
Willy Tarreaubaaee002006-06-26 02:48:02 +02006070 if (*(args[1]) == 0) {
6071 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006072 err_code |= ERR_ALERT | ERR_FATAL;
6073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006074 }
6075
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006076 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006077 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6078 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6079 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006080 err_code |= ERR_ALERT | ERR_FATAL;
6081 goto out;
6082 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006083 err_code |= warnif_cond_conflicts(cond,
6084 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6085 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006086 }
6087 else if (*args[2]) {
6088 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6089 file, linenum, args[0], args[2]);
6090 err_code |= ERR_ALERT | ERR_FATAL;
6091 goto out;
6092 }
6093
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006094 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006095 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006096 wl->s = strdup(args[1]);
6097 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006098 }
6099 else if (!strcmp(args[0], "errorloc") ||
6100 !strcmp(args[0], "errorloc302") ||
6101 !strcmp(args[0], "errorloc303")) { /* error location */
6102 int errnum, errlen;
6103 char *err;
6104
Willy Tarreau977b8e42006-12-29 14:19:17 +01006105 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006106 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006107
Willy Tarreaubaaee002006-06-26 02:48:02 +02006108 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006109 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006110 err_code |= ERR_ALERT | ERR_FATAL;
6111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006112 }
6113
6114 errnum = atol(args[1]);
6115 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006116 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6117 err = malloc(errlen);
6118 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006119 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006120 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6121 err = malloc(errlen);
6122 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006123 }
6124
Willy Tarreau0f772532006-12-23 20:51:41 +01006125 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6126 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006127 chunk_destroy(&curproxy->errmsg[rc]);
6128 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006129 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006130 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006131 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006132
6133 if (rc >= HTTP_ERR_SIZE) {
6134 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
6135 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006136 free(err);
6137 }
6138 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006139 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6140 int errnum, errlen, fd;
6141 char *err;
6142 struct stat stat;
6143
6144 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006145 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006146
6147 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006148 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006149 err_code |= ERR_ALERT | ERR_FATAL;
6150 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006151 }
6152
6153 fd = open(args[2], O_RDONLY);
6154 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6155 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6156 file, linenum, args[2], args[1]);
6157 if (fd >= 0)
6158 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006159 err_code |= ERR_ALERT | ERR_FATAL;
6160 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006161 }
6162
Willy Tarreau27a674e2009-08-17 07:23:33 +02006163 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006164 errlen = stat.st_size;
6165 } else {
6166 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006167 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006168 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006169 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006170 }
6171
6172 err = malloc(errlen); /* malloc() must succeed during parsing */
6173 errnum = read(fd, err, errlen);
6174 if (errnum != errlen) {
6175 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6176 file, linenum, args[2], args[1]);
6177 close(fd);
6178 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006179 err_code |= ERR_ALERT | ERR_FATAL;
6180 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006181 }
6182 close(fd);
6183
6184 errnum = atol(args[1]);
6185 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6186 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006187 chunk_destroy(&curproxy->errmsg[rc]);
6188 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006189 break;
6190 }
6191 }
6192
6193 if (rc >= HTTP_ERR_SIZE) {
6194 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
6195 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02006196 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006197 free(err);
6198 }
6199 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006200 else if (!strcmp(args[0], "compression")) {
6201 struct comp *comp;
6202 if (curproxy->comp == NULL) {
6203 comp = calloc(1, sizeof(struct comp));
6204 curproxy->comp = comp;
6205 } else {
6206 comp = curproxy->comp;
6207 }
6208
6209 if (!strcmp(args[1], "algo")) {
6210 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006211 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006212
William Lallemand82fe75c2012-10-23 10:25:10 +02006213 cur_arg = 2;
6214 if (!*args[cur_arg]) {
6215 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6216 file, linenum, args[0]);
6217 err_code |= ERR_ALERT | ERR_FATAL;
6218 goto out;
6219 }
6220 while (*(args[cur_arg])) {
6221 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6222 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6223 file, linenum, args[0], args[cur_arg]);
6224 err_code |= ERR_ALERT | ERR_FATAL;
6225 goto out;
6226 }
William Lallemand552df672012-11-07 13:21:47 +01006227 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6228 curproxy->comp->algos->end(&ctx);
6229 } else {
6230 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6231 file, linenum, args[0], args[cur_arg]);
6232 err_code |= ERR_ALERT | ERR_FATAL;
6233 goto out;
6234 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006235 cur_arg ++;
6236 continue;
6237 }
6238 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006239 else if (!strcmp(args[1], "offload")) {
6240 comp->offload = 1;
6241 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006242 else if (!strcmp(args[1], "type")) {
6243 int cur_arg;
6244 cur_arg = 2;
6245 if (!*args[cur_arg]) {
6246 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6247 file, linenum, args[0]);
6248 err_code |= ERR_ALERT | ERR_FATAL;
6249 goto out;
6250 }
6251 while (*(args[cur_arg])) {
6252 comp_append_type(comp, args[cur_arg]);
6253 cur_arg ++;
6254 continue;
6255 }
6256 }
6257 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006258 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006259 file, linenum, args[0]);
6260 err_code |= ERR_ALERT | ERR_FATAL;
6261 goto out;
6262 }
6263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006264 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006265 struct cfg_kw_list *kwl;
6266 int index;
6267
6268 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6269 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6270 if (kwl->kw[index].section != CFG_LISTEN)
6271 continue;
6272 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6273 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006274 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006275 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006276 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006277 err_code |= ERR_ALERT | ERR_FATAL;
6278 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006279 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006280 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006281 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006282 err_code |= ERR_WARN;
6283 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006284 }
Willy Tarreau93893792009-07-23 13:19:11 +02006285 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006286 }
6287 }
6288 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006289
Willy Tarreau6daf3432008-01-22 16:44:08 +01006290 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006291 err_code |= ERR_ALERT | ERR_FATAL;
6292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006293 }
Willy Tarreau93893792009-07-23 13:19:11 +02006294 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006295 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006296 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006297}
6298
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006299int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006300cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6301{
6302#ifdef CONFIG_HAP_NS
6303 const char *err;
6304 const char *item = args[0];
6305
6306 if (!strcmp(item, "namespace_list")) {
6307 return 0;
6308 }
6309 else if (!strcmp(item, "namespace")) {
6310 size_t idx = 1;
6311 const char *current;
6312 while (*(current = args[idx++])) {
6313 err = invalid_char(current);
6314 if (err) {
6315 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6316 file, linenum, *err, item, current);
6317 return ERR_ALERT | ERR_FATAL;
6318 }
6319
6320 if (netns_store_lookup(current, strlen(current))) {
6321 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6322 file, linenum, current);
6323 return ERR_ALERT | ERR_FATAL;
6324 }
6325 if (!netns_store_insert(current)) {
6326 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6327 file, linenum, current);
6328 return ERR_ALERT | ERR_FATAL;
6329 }
6330 }
6331 }
6332
6333 return 0;
6334#else
6335 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6336 file, linenum);
6337 return ERR_ALERT | ERR_FATAL;
6338#endif
6339}
6340
6341int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006342cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6343{
6344
6345 int err_code = 0;
6346 const char *err;
6347
6348 if (!strcmp(args[0], "userlist")) { /* new userlist */
6349 struct userlist *newul;
6350
6351 if (!*args[1]) {
6352 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6353 file, linenum, args[0]);
6354 err_code |= ERR_ALERT | ERR_FATAL;
6355 goto out;
6356 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006357 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6358 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006359
6360 err = invalid_char(args[1]);
6361 if (err) {
6362 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6363 file, linenum, *err, args[0], args[1]);
6364 err_code |= ERR_ALERT | ERR_FATAL;
6365 goto out;
6366 }
6367
6368 for (newul = userlist; newul; newul = newul->next)
6369 if (!strcmp(newul->name, args[1])) {
6370 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6371 file, linenum, args[1]);
6372 err_code |= ERR_WARN;
6373 goto out;
6374 }
6375
6376 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6377 if (!newul) {
6378 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6379 err_code |= ERR_ALERT | ERR_ABORT;
6380 goto out;
6381 }
6382
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006383 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006384 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006385 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6386 err_code |= ERR_ALERT | ERR_ABORT;
6387 goto out;
6388 }
6389
6390 newul->next = userlist;
6391 userlist = newul;
6392
6393 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006394 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006395 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006396 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006397
6398 if (!*args[1]) {
6399 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6400 file, linenum, args[0]);
6401 err_code |= ERR_ALERT | ERR_FATAL;
6402 goto out;
6403 }
6404
6405 err = invalid_char(args[1]);
6406 if (err) {
6407 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6408 file, linenum, *err, args[0], args[1]);
6409 err_code |= ERR_ALERT | ERR_FATAL;
6410 goto out;
6411 }
6412
William Lallemand4ac9f542015-05-28 18:03:51 +02006413 if (!userlist)
6414 goto out;
6415
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006416 for (ag = userlist->groups; ag; ag = ag->next)
6417 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006418 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6419 file, linenum, args[1], userlist->name);
6420 err_code |= ERR_ALERT;
6421 goto out;
6422 }
6423
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006424 ag = calloc(1, sizeof(*ag));
6425 if (!ag) {
6426 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6427 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006428 goto out;
6429 }
6430
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006431 ag->name = strdup(args[1]);
6432 if (!ag) {
6433 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6434 err_code |= ERR_ALERT | ERR_ABORT;
6435 goto out;
6436 }
6437
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006438 cur_arg = 2;
6439
6440 while (*args[cur_arg]) {
6441 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006442 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006443 cur_arg += 2;
6444 continue;
6445 } else {
6446 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6447 file, linenum, args[0]);
6448 err_code |= ERR_ALERT | ERR_FATAL;
6449 goto out;
6450 }
6451 }
6452
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006453 ag->next = userlist->groups;
6454 userlist->groups = ag;
6455
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006456 } else if (!strcmp(args[0], "user")) { /* new user */
6457 struct auth_users *newuser;
6458 int cur_arg;
6459
6460 if (!*args[1]) {
6461 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6462 file, linenum, args[0]);
6463 err_code |= ERR_ALERT | ERR_FATAL;
6464 goto out;
6465 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006466 if (!userlist)
6467 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006468
6469 for (newuser = userlist->users; newuser; newuser = newuser->next)
6470 if (!strcmp(newuser->user, args[1])) {
6471 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6472 file, linenum, args[1], userlist->name);
6473 err_code |= ERR_ALERT;
6474 goto out;
6475 }
6476
6477 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6478 if (!newuser) {
6479 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6480 err_code |= ERR_ALERT | ERR_ABORT;
6481 goto out;
6482 }
6483
6484 newuser->user = strdup(args[1]);
6485
6486 newuser->next = userlist->users;
6487 userlist->users = newuser;
6488
6489 cur_arg = 2;
6490
6491 while (*args[cur_arg]) {
6492 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006493#ifdef CONFIG_HAP_CRYPT
6494 if (!crypt("", args[cur_arg + 1])) {
6495 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6496 file, linenum, newuser->user);
6497 err_code |= ERR_ALERT | ERR_FATAL;
6498 goto out;
6499 }
6500#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006501 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6502 file, linenum);
6503 err_code |= ERR_ALERT;
6504#endif
6505 newuser->pass = strdup(args[cur_arg + 1]);
6506 cur_arg += 2;
6507 continue;
6508 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6509 newuser->pass = strdup(args[cur_arg + 1]);
6510 newuser->flags |= AU_O_INSECURE;
6511 cur_arg += 2;
6512 continue;
6513 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006514 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006515 cur_arg += 2;
6516 continue;
6517 } else {
6518 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6519 file, linenum, args[0]);
6520 err_code |= ERR_ALERT | ERR_FATAL;
6521 goto out;
6522 }
6523 }
6524 } else {
6525 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6526 err_code |= ERR_ALERT | ERR_FATAL;
6527 }
6528
6529out:
6530 return err_code;
6531}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006532
6533/*
6534 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006535 * Returns the error code, 0 if OK, or any combination of :
6536 * - ERR_ABORT: must abort ASAP
6537 * - ERR_FATAL: we can continue parsing but not start the service
6538 * - ERR_WARN: a warning has been emitted
6539 * - ERR_ALERT: an alert has been emitted
6540 * Only the two first ones can stop processing, the two others are just
6541 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006542 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006543int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006544{
William Lallemand64e84512015-05-12 14:25:37 +02006545 char *thisline;
6546 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006547 FILE *f;
6548 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006549 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006550 struct cfg_section *cs = NULL;
6551 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006552 int readbytes = 0;
6553
6554 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006555 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006556 return -1;
6557 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006558
6559 /* Register internal sections */
6560 if (!cfg_register_section("listen", cfg_parse_listen) ||
6561 !cfg_register_section("frontend", cfg_parse_listen) ||
6562 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006563 !cfg_register_section("defaults", cfg_parse_listen) ||
6564 !cfg_register_section("global", cfg_parse_global) ||
6565 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006566 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006567 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006568 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006569 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006570
Willy Tarreaubaaee002006-06-26 02:48:02 +02006571 if ((f=fopen(file,"r")) == NULL)
6572 return -1;
6573
William Lallemandb2f07452015-05-12 14:27:13 +02006574next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006575 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006576 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006577 char *end;
6578 char *args[MAX_LINE_ARGS + 1];
6579 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006580 int dquote = 0; /* double quote */
6581 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006582
Willy Tarreaubaaee002006-06-26 02:48:02 +02006583 linenum++;
6584
6585 end = line + strlen(line);
6586
William Lallemand64e84512015-05-12 14:25:37 +02006587 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006588 /* Check if we reached the limit and the last char is not \n.
6589 * Watch out for the last line without the terminating '\n'!
6590 */
William Lallemand64e84512015-05-12 14:25:37 +02006591 char *newline;
6592 int newlinesize = linesize * 2;
6593
6594 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6595 if (newline == NULL) {
6596 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6597 file, linenum);
6598 err_code |= ERR_ALERT | ERR_FATAL;
6599 continue;
6600 }
6601
6602 readbytes = linesize - 1;
6603 linesize = newlinesize;
6604 thisline = newline;
6605 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006606 }
6607
William Lallemand64e84512015-05-12 14:25:37 +02006608 readbytes = 0;
6609
Willy Tarreaubaaee002006-06-26 02:48:02 +02006610 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006611 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006612 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006613
Willy Tarreaubaaee002006-06-26 02:48:02 +02006614 arg = 0;
6615 args[arg] = line;
6616
6617 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006618 if (*line == '"' && !squote) { /* double quote outside single quotes */
6619 if (dquote)
6620 dquote = 0;
6621 else
6622 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006623 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006624 end--;
6625 }
6626 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6627 if (squote)
6628 squote = 0;
6629 else
6630 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006631 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006632 end--;
6633 }
6634 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006635 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6636 * C equivalent value. Other combinations left unchanged (eg: \1).
6637 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006638 int skip = 0;
6639 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6640 *line = line[1];
6641 skip = 1;
6642 }
6643 else if (line[1] == 'r') {
6644 *line = '\r';
6645 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006646 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006647 else if (line[1] == 'n') {
6648 *line = '\n';
6649 skip = 1;
6650 }
6651 else if (line[1] == 't') {
6652 *line = '\t';
6653 skip = 1;
6654 }
6655 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006656 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006657 unsigned char hex1, hex2;
6658 hex1 = toupper(line[2]) - '0';
6659 hex2 = toupper(line[3]) - '0';
6660 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6661 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6662 *line = (hex1<<4) + hex2;
6663 skip = 3;
6664 }
6665 else {
6666 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006667 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006668 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006669 } else if (line[1] == '"') {
6670 *line = '"';
6671 skip = 1;
6672 } else if (line[1] == '\'') {
6673 *line = '\'';
6674 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006675 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6676 *line = '$';
6677 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006678 }
6679 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006680 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006681 end -= skip;
6682 }
6683 line++;
6684 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006685 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006686 /* end of string, end of loop */
6687 *line = 0;
6688 break;
6689 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006690 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006691 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006692 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006693 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006694 line++;
6695 args[++arg] = line;
6696 }
William Lallemandb2f07452015-05-12 14:27:13 +02006697 else if (dquote && *line == '$') {
6698 /* environment variables are evaluated inside double quotes */
6699 char *var_beg;
6700 char *var_end;
6701 char save_char;
6702 char *value;
6703 int val_len;
6704 int newlinesize;
6705 int braces = 0;
6706
6707 var_beg = line + 1;
6708 var_end = var_beg;
6709
6710 if (*var_beg == '{') {
6711 var_beg++;
6712 var_end++;
6713 braces = 1;
6714 }
6715
6716 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6717 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6718 err_code |= ERR_ALERT | ERR_FATAL;
6719 goto next_line; /* skip current line */
6720 }
6721
6722 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6723 var_end++;
6724
6725 save_char = *var_end;
6726 *var_end = '\0';
6727 value = getenv(var_beg);
6728 *var_end = save_char;
6729 val_len = value ? strlen(value) : 0;
6730
6731 if (braces) {
6732 if (*var_end == '}') {
6733 var_end++;
6734 braces = 0;
6735 } else {
6736 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
6737 err_code |= ERR_ALERT | ERR_FATAL;
6738 goto next_line; /* skip current line */
6739 }
6740 }
6741
6742 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
6743
6744 /* if not enough space in thisline */
6745 if (newlinesize > linesize) {
6746 char *newline;
6747
6748 newline = realloc(thisline, newlinesize * sizeof(*thisline));
6749 if (newline == NULL) {
6750 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
6751 err_code |= ERR_ALERT | ERR_FATAL;
6752 goto next_line; /* slip current line */
6753 }
6754 /* recompute pointers if realloc returns a new pointer */
6755 if (newline != thisline) {
6756 int i;
6757 int diff;
6758
6759 for (i = 0; i <= arg; i++) {
6760 diff = args[i] - thisline;
6761 args[i] = newline + diff;
6762 }
6763
6764 diff = var_end - thisline;
6765 var_end = newline + diff;
6766 diff = end - thisline;
6767 end = newline + diff;
6768 diff = line - thisline;
6769 line = newline + diff;
6770 thisline = newline;
6771 }
6772 linesize = newlinesize;
6773 }
6774
6775 /* insert value inside the line */
6776 memmove(line + val_len, var_end, end - var_end + 1);
6777 memcpy(line, value, val_len);
6778 end += val_len - (var_end - line);
6779 line += val_len;
6780 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006781 else {
6782 line++;
6783 }
6784 }
William Lallemandb2f07452015-05-12 14:27:13 +02006785
William Lallemandf9873ba2015-05-05 17:37:14 +02006786 if (dquote) {
6787 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
6788 err_code |= ERR_ALERT | ERR_FATAL;
6789 }
6790
6791 if (squote) {
6792 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
6793 err_code |= ERR_ALERT | ERR_FATAL;
6794 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006795
6796 /* empty line */
6797 if (!**args)
6798 continue;
6799
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006800 if (*line) {
6801 /* we had to stop due to too many args.
6802 * Let's terminate the string, print the offending part then cut the
6803 * last arg.
6804 */
6805 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6806 line++;
6807 *line = '\0';
6808
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006809 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006810 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006811 err_code |= ERR_ALERT | ERR_FATAL;
6812 args[arg] = line;
6813 }
6814
Willy Tarreau540abe42007-05-02 20:50:16 +02006815 /* zero out remaining args and ensure that at least one entry
6816 * is zeroed out.
6817 */
6818 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006819 args[arg] = line;
6820 }
6821
Willy Tarreau3842f002009-06-14 11:39:52 +02006822 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006823 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006824 char *tmp;
6825
Willy Tarreau3842f002009-06-14 11:39:52 +02006826 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006827 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006828 for (arg=0; *args[arg+1]; arg++)
6829 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006830 *tmp = '\0'; // fix the next arg to \0
6831 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006832 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006833 else if (!strcmp(args[0], "default")) {
6834 kwm = KWM_DEF;
6835 for (arg=0; *args[arg+1]; arg++)
6836 args[arg] = args[arg+1]; // shift args after inversion
6837 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006838
William Lallemand0f99e342011-10-12 17:50:54 +02006839 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6840 strcmp(args[0], "log") != 0) {
6841 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006842 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006843 }
6844
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006845 /* detect section start */
6846 list_for_each_entry(ics, &sections, list) {
6847 if (strcmp(args[0], ics->section_name) == 0) {
6848 cursection = ics->section_name;
6849 cs = ics;
6850 break;
6851 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006852 }
6853
Willy Tarreaubaaee002006-06-26 02:48:02 +02006854 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006855 if (cs)
6856 err_code |= cs->section_parser(file, linenum, args, kwm);
6857 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006858 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006859 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006860 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006861
6862 if (err_code & ERR_ABORT)
6863 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006864 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006865 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02006866 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006867 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006868 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006869}
6870
Willy Tarreau64ab6072014-09-16 12:17:36 +02006871/* This function propagates processes from frontend <from> to backend <to> so
6872 * that it is always guaranteed that a backend pointed to by a frontend is
6873 * bound to all of its processes. After that, if the target is a "listen"
6874 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02006875 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02006876 * checked first to ensure that <to> is already bound to all processes of
6877 * <from>, there is no risk of looping and we ensure to follow the shortest
6878 * path to the destination.
6879 *
6880 * It is possible to set <to> to NULL for the first call so that the function
6881 * takes care of visiting the initial frontend in <from>.
6882 *
6883 * It is important to note that the function relies on the fact that all names
6884 * have already been resolved.
6885 */
6886void propagate_processes(struct proxy *from, struct proxy *to)
6887{
6888 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006889
6890 if (to) {
6891 /* check whether we need to go down */
6892 if (from->bind_proc &&
6893 (from->bind_proc & to->bind_proc) == from->bind_proc)
6894 return;
6895
6896 if (!from->bind_proc && !to->bind_proc)
6897 return;
6898
6899 to->bind_proc = from->bind_proc ?
6900 (to->bind_proc | from->bind_proc) : 0;
6901
6902 /* now propagate down */
6903 from = to;
6904 }
6905
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006906 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006907 return;
6908
Willy Tarreauf6b70012014-12-18 14:00:43 +01006909 if (from->state == PR_STSTOPPED)
6910 return;
6911
Willy Tarreau64ab6072014-09-16 12:17:36 +02006912 /* default_backend */
6913 if (from->defbe.be)
6914 propagate_processes(from, from->defbe.be);
6915
6916 /* use_backend */
6917 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006918 if (rule->dynamic)
6919 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006920 to = rule->be.backend;
6921 propagate_processes(from, to);
6922 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02006923}
6924
Willy Tarreaubb925012009-07-23 13:36:36 +02006925/*
6926 * Returns the error code, 0 if OK, or any combination of :
6927 * - ERR_ABORT: must abort ASAP
6928 * - ERR_FATAL: we can continue parsing but not start the service
6929 * - ERR_WARN: a warning has been emitted
6930 * - ERR_ALERT: an alert has been emitted
6931 * Only the two first ones can stop processing, the two others are just
6932 * indicators.
6933 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006934int check_config_validity()
6935{
6936 int cfgerr = 0;
6937 struct proxy *curproxy = NULL;
6938 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006939 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006940 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006941 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006942
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006943 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006944 /*
6945 * Now, check for the integrity of all that we have collected.
6946 */
6947
6948 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006949 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006950
Willy Tarreau193b8c62012-11-22 00:17:38 +01006951 if (!global.tune.max_http_hdr)
6952 global.tune.max_http_hdr = MAX_HTTP_HDR;
6953
6954 if (!global.tune.cookie_len)
6955 global.tune.cookie_len = CAPTURE_LEN;
6956
6957 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6958
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006959 /* Post initialisation of the users and groups lists. */
6960 err_code = userlist_postinit();
6961 if (err_code != ERR_NONE)
6962 goto out;
6963
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006964 /* first, we will invert the proxy list order */
6965 curproxy = NULL;
6966 while (proxy) {
6967 struct proxy *next;
6968
6969 next = proxy->next;
6970 proxy->next = curproxy;
6971 curproxy = proxy;
6972 if (!next)
6973 break;
6974 proxy = next;
6975 }
6976
Willy Tarreau419ead82014-09-16 13:41:21 +02006977 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006978 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006979 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006980 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006981 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006982 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006983 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006984 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006985
Willy Tarreau050536d2012-10-04 08:47:34 +02006986 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006987 /* proxy ID not set, use automatic numbering with first
6988 * spare entry starting with next_pxid.
6989 */
6990 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6991 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6992 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006993 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006994 next_pxid++;
6995
Willy Tarreau55ea7572007-06-17 19:56:27 +02006996
Willy Tarreaubaaee002006-06-26 02:48:02 +02006997 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006998 /* ensure we don't keep listeners uselessly bound */
6999 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007000 free((void *)curproxy->table.peers.name);
7001 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007002 continue;
7003 }
7004
Willy Tarreau102df612014-05-07 23:56:38 +02007005 /* Check multi-process mode compatibility for the current proxy */
7006
7007 if (curproxy->bind_proc) {
7008 /* an explicit bind-process was specified, let's check how many
7009 * processes remain.
7010 */
7011 nbproc = popcount(curproxy->bind_proc);
7012
7013 curproxy->bind_proc &= nbits(global.nbproc);
7014 if (!curproxy->bind_proc && nbproc == 1) {
7015 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);
7016 curproxy->bind_proc = 1;
7017 }
7018 else if (!curproxy->bind_proc && nbproc > 1) {
7019 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);
7020 curproxy->bind_proc = 0;
7021 }
7022 }
7023
Willy Tarreau3d209582014-05-09 17:06:11 +02007024 /* check and reduce the bind-proc of each listener */
7025 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7026 unsigned long mask;
7027
7028 if (!bind_conf->bind_proc)
7029 continue;
7030
7031 mask = nbits(global.nbproc);
7032 if (curproxy->bind_proc)
7033 mask &= curproxy->bind_proc;
7034 /* mask cannot be null here thanks to the previous checks */
7035
7036 nbproc = popcount(bind_conf->bind_proc);
7037 bind_conf->bind_proc &= mask;
7038
7039 if (!bind_conf->bind_proc && nbproc == 1) {
7040 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",
7041 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7042 bind_conf->bind_proc = mask & ~(mask - 1);
7043 }
7044 else if (!bind_conf->bind_proc && nbproc > 1) {
7045 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",
7046 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7047 bind_conf->bind_proc = 0;
7048 }
7049 }
7050
Willy Tarreauff01a212009-03-15 13:46:16 +01007051 switch (curproxy->mode) {
7052 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007053 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007054 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007055 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7056 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007057 cfgerr++;
7058 }
7059
7060 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007061 Warning("config : servers will be ignored for %s '%s'.\n",
7062 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007063 break;
7064
7065 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007066 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007067 break;
7068
7069 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007070 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007071 break;
7072 }
7073
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007074 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007075 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007076 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007077 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7078 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007079 cfgerr++;
7080 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007081#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007082 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007083 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7084 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007085 cfgerr++;
7086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007087#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007088 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007089 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7090 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007091 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007092 }
7093 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007094 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007095 /* If no LB algo is set in a backend, and we're not in
7096 * transparent mode, dispatch mode nor proxy mode, we
7097 * want to use balance roundrobin by default.
7098 */
7099 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7100 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007101 }
7102 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007103
Willy Tarreau1620ec32011-08-06 17:05:02 +02007104 if (curproxy->options & PR_O_DISPATCH)
7105 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7106 else if (curproxy->options & PR_O_HTTP_PROXY)
7107 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7108 else if (curproxy->options & PR_O_TRANSP)
7109 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007110
Willy Tarreau1620ec32011-08-06 17:05:02 +02007111 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7112 if (curproxy->options & PR_O_DISABLE404) {
7113 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7114 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7115 err_code |= ERR_WARN;
7116 curproxy->options &= ~PR_O_DISABLE404;
7117 }
7118 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7119 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7120 "send-state", proxy_type_str(curproxy), curproxy->id);
7121 err_code |= ERR_WARN;
7122 curproxy->options &= ~PR_O2_CHK_SNDST;
7123 }
Willy Tarreauef781042010-01-27 11:53:01 +01007124 }
7125
Simon Horman98637e52014-06-20 12:30:16 +09007126 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7127 if (!global.external_check) {
7128 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7129 curproxy->id, "option external-check");
7130 cfgerr++;
7131 }
7132 if (!curproxy->check_command) {
7133 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7134 curproxy->id, "option external-check");
7135 cfgerr++;
7136 }
7137 }
7138
Simon Horman64e34162015-02-06 11:11:57 +09007139 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007140 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7141 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09007142 "'email-alert from', 'email-alert level' 'email-alert mailer', "
7143 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007144 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
7145 "to be present).\n",
7146 proxy_type_str(curproxy), curproxy->id);
7147 err_code |= ERR_WARN;
7148 free_email_alert(curproxy);
7149 }
7150 if (!curproxy->email_alert.myhostname)
7151 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09007152 }
7153
Simon Horman98637e52014-06-20 12:30:16 +09007154 if (curproxy->check_command) {
7155 int clear = 0;
7156 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7157 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7158 "external-check command", proxy_type_str(curproxy), curproxy->id);
7159 err_code |= ERR_WARN;
7160 clear = 1;
7161 }
7162 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
7163 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
7164 curproxy->id, "external-check command");
7165 cfgerr++;
7166 }
7167 if (clear) {
7168 free(curproxy->check_command);
7169 curproxy->check_command = NULL;
7170 }
7171 }
7172
7173 if (curproxy->check_path) {
7174 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7175 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7176 "external-check path", proxy_type_str(curproxy), curproxy->id);
7177 err_code |= ERR_WARN;
7178 free(curproxy->check_path);
7179 curproxy->check_path = NULL;
7180 }
7181 }
7182
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007183 /* if a default backend was specified, let's find it */
7184 if (curproxy->defbe.name) {
7185 struct proxy *target;
7186
Willy Tarreauafb39922015-05-26 12:04:09 +02007187 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007188 if (!target) {
7189 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7190 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007191 cfgerr++;
7192 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007193 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7194 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007195 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007196 } else if (target->mode != curproxy->mode &&
7197 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7198
7199 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7200 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7201 curproxy->conf.file, curproxy->conf.line,
7202 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7203 target->conf.file, target->conf.line);
7204 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007205 } else {
7206 free(curproxy->defbe.name);
7207 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007208
7209 /* Emit a warning if this proxy also has some servers */
7210 if (curproxy->srv) {
7211 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7212 curproxy->id);
7213 err_code |= ERR_WARN;
7214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007215 }
7216 }
7217
Willy Tarreau55ea7572007-06-17 19:56:27 +02007218 /* find the target proxy for 'use_backend' rules */
7219 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007220 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007221 struct logformat_node *node;
7222 char *pxname;
7223
7224 /* Try to parse the string as a log format expression. If the result
7225 * of the parsing is only one entry containing a simple string, then
7226 * it's a standard string corresponding to a static rule, thus the
7227 * parsing is cancelled and be.name is restored to be resolved.
7228 */
7229 pxname = rule->be.name;
7230 LIST_INIT(&rule->be.expr);
7231 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7232 curproxy->conf.args.file, curproxy->conf.args.line);
7233 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7234
7235 if (!LIST_ISEMPTY(&rule->be.expr)) {
7236 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7237 rule->dynamic = 1;
7238 free(pxname);
7239 continue;
7240 }
7241 /* simple string: free the expression and fall back to static rule */
7242 free(node->arg);
7243 free(node);
7244 }
7245
7246 rule->dynamic = 0;
7247 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007248
Willy Tarreauafb39922015-05-26 12:04:09 +02007249 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007250 if (!target) {
7251 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7252 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007253 cfgerr++;
7254 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007255 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7256 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007257 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007258 } else if (target->mode != curproxy->mode &&
7259 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7260
7261 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7262 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7263 curproxy->conf.file, curproxy->conf.line,
7264 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7265 target->conf.file, target->conf.line);
7266 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007267 } else {
7268 free((void *)rule->be.name);
7269 rule->be.backend = target;
7270 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007271 }
7272
Willy Tarreau64ab6072014-09-16 12:17:36 +02007273 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007274 list_for_each_entry(srule, &curproxy->server_rules, list) {
7275 struct server *target = findserver(curproxy, srule->srv.name);
7276
7277 if (!target) {
7278 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7279 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7280 cfgerr++;
7281 continue;
7282 }
7283 free((void *)srule->srv.name);
7284 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007285 }
7286
Emeric Brunb982a3d2010-01-04 15:45:53 +01007287 /* find the target table for 'stick' rules */
7288 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7289 struct proxy *target;
7290
Emeric Brun1d33b292010-01-04 15:47:17 +01007291 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7292 if (mrule->flags & STK_IS_STORE)
7293 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7294
Emeric Brunb982a3d2010-01-04 15:45:53 +01007295 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007296 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007297 else
7298 target = curproxy;
7299
7300 if (!target) {
7301 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7302 curproxy->id, mrule->table.name);
7303 cfgerr++;
7304 }
7305 else if (target->table.size == 0) {
7306 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7307 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7308 cfgerr++;
7309 }
Willy Tarreau12785782012-04-27 21:37:17 +02007310 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7311 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007312 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7313 cfgerr++;
7314 }
7315 else {
7316 free((void *)mrule->table.name);
7317 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007318 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007319 }
7320 }
7321
7322 /* find the target table for 'store response' rules */
7323 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7324 struct proxy *target;
7325
Emeric Brun1d33b292010-01-04 15:47:17 +01007326 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7327
Emeric Brunb982a3d2010-01-04 15:45:53 +01007328 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007329 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007330 else
7331 target = curproxy;
7332
7333 if (!target) {
7334 Alert("Proxy '%s': unable to find store table '%s'.\n",
7335 curproxy->id, mrule->table.name);
7336 cfgerr++;
7337 }
7338 else if (target->table.size == 0) {
7339 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7340 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7341 cfgerr++;
7342 }
Willy Tarreau12785782012-04-27 21:37:17 +02007343 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7344 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007345 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7346 cfgerr++;
7347 }
7348 else {
7349 free((void *)mrule->table.name);
7350 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007351 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007352 }
7353 }
7354
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007355 /* find the target table for 'tcp-request' layer 4 rules */
7356 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7357 struct proxy *target;
7358
Willy Tarreaub4c84932013-07-23 19:15:30 +02007359 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007360 continue;
7361
7362 if (trule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007363 target = proxy_tbl_by_name(trule->act_prm.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007364 else
7365 target = curproxy;
7366
7367 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007368 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7369 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007370 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007371 cfgerr++;
7372 }
7373 else if (target->table.size == 0) {
7374 Alert("Proxy '%s': table '%s' used but not configured.\n",
7375 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7376 cfgerr++;
7377 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007378 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7379 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7380 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 +01007381 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007382 cfgerr++;
7383 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007384 else {
7385 free(trule->act_prm.trk_ctr.table.n);
7386 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007387 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007388 * to pass a list of counters to track and allocate them right here using
7389 * stktable_alloc_data_type().
7390 */
7391 }
7392 }
7393
Willy Tarreaud1f96522010-08-03 19:34:32 +02007394 /* find the target table for 'tcp-request' layer 6 rules */
7395 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7396 struct proxy *target;
7397
Willy Tarreaub4c84932013-07-23 19:15:30 +02007398 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007399 continue;
7400
7401 if (trule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007402 target = proxy_tbl_by_name(trule->act_prm.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007403 else
7404 target = curproxy;
7405
7406 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007407 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7408 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007409 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007410 cfgerr++;
7411 }
7412 else if (target->table.size == 0) {
7413 Alert("Proxy '%s': table '%s' used but not configured.\n",
7414 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7415 cfgerr++;
7416 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007417 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7418 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7419 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 +01007420 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007421 cfgerr++;
7422 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007423 else {
7424 free(trule->act_prm.trk_ctr.table.n);
7425 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007426 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007427 * to pass a list of counters to track and allocate them right here using
7428 * stktable_alloc_data_type().
7429 */
7430 }
7431 }
7432
Willy Tarreau09448f72014-06-25 18:12:15 +02007433 /* find the target table for 'http-request' layer 7 rules */
7434 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7435 struct proxy *target;
7436
7437 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
7438 continue;
7439
7440 if (hrqrule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007441 target = proxy_tbl_by_name(hrqrule->act_prm.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007442 else
7443 target = curproxy;
7444
7445 if (!target) {
7446 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7447 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
7448 http_req_trk_idx(hrqrule->action));
7449 cfgerr++;
7450 }
7451 else if (target->table.size == 0) {
7452 Alert("Proxy '%s': table '%s' used but not configured.\n",
7453 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
7454 cfgerr++;
7455 }
7456 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
7457 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7458 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
7459 http_req_trk_idx(hrqrule->action));
7460 cfgerr++;
7461 }
7462 else {
7463 free(hrqrule->act_prm.trk_ctr.table.n);
7464 hrqrule->act_prm.trk_ctr.table.t = &target->table;
7465 /* Note: if we decide to enhance the track-sc syntax, we may be able
7466 * to pass a list of counters to track and allocate them right here using
7467 * stktable_alloc_data_type().
7468 */
7469 }
7470 }
7471
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007472 /* move any "block" rules at the beginning of the http-request rules */
7473 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7474 /* insert block_rules into http_req_rules at the beginning */
7475 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7476 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7477 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7478 curproxy->http_req_rules.n = curproxy->block_rules.n;
7479 LIST_INIT(&curproxy->block_rules);
7480 }
7481
Emeric Brun32da3c42010-09-23 18:39:19 +02007482 if (curproxy->table.peers.name) {
7483 struct peers *curpeers = peers;
7484
7485 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7486 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7487 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007488 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007489 break;
7490 }
7491 }
7492
7493 if (!curpeers) {
7494 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7495 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007496 free((void *)curproxy->table.peers.name);
7497 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007498 cfgerr++;
7499 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007500 else if (curpeers->state == PR_STSTOPPED) {
7501 /* silently disable this peers section */
7502 curproxy->table.peers.p = NULL;
7503 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007504 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007505 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7506 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007507 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007508 cfgerr++;
7509 }
7510 }
7511
Simon Horman9dc49962015-01-30 11:22:59 +09007512
7513 if (curproxy->email_alert.mailers.name) {
7514 struct mailers *curmailers = mailers;
7515
7516 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7517 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7518 free(curproxy->email_alert.mailers.name);
7519 curproxy->email_alert.mailers.m = curmailers;
7520 curmailers->users++;
7521 break;
7522 }
7523 }
7524
7525 if (!curmailers) {
7526 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7527 curproxy->id, curproxy->email_alert.mailers.name);
7528 free_email_alert(curproxy);
7529 cfgerr++;
7530 }
7531 }
7532
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007533 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007534 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007535 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7536 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7537 "proxy", curproxy->id);
7538 cfgerr++;
7539 goto out_uri_auth_compat;
7540 }
7541
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007542 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007543 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007544 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007545 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007546
Willy Tarreau95fa4692010-02-01 13:05:50 +01007547 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7548 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007549
7550 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007551 uri_auth_compat_req[i++] = "realm";
7552 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7553 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007554
Willy Tarreau95fa4692010-02-01 13:05:50 +01007555 uri_auth_compat_req[i++] = "unless";
7556 uri_auth_compat_req[i++] = "{";
7557 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7558 uri_auth_compat_req[i++] = "}";
7559 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007560
Willy Tarreauff011f22011-01-06 17:51:27 +01007561 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7562 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007563 cfgerr++;
7564 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007565 }
7566
Willy Tarreauff011f22011-01-06 17:51:27 +01007567 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007568
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007569 if (curproxy->uri_auth->auth_realm) {
7570 free(curproxy->uri_auth->auth_realm);
7571 curproxy->uri_auth->auth_realm = NULL;
7572 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007573
7574 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007575 }
7576out_uri_auth_compat:
7577
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007578 /* compile the log format */
7579 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007580 if (curproxy->conf.logformat_string != default_http_log_format &&
7581 curproxy->conf.logformat_string != default_tcp_log_format &&
7582 curproxy->conf.logformat_string != clf_http_log_format)
7583 free(curproxy->conf.logformat_string);
7584 curproxy->conf.logformat_string = NULL;
7585 free(curproxy->conf.lfs_file);
7586 curproxy->conf.lfs_file = NULL;
7587 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007588 }
7589
Willy Tarreau62a61232013-04-12 18:13:46 +02007590 if (curproxy->conf.logformat_string) {
7591 curproxy->conf.args.ctx = ARGC_LOG;
7592 curproxy->conf.args.file = curproxy->conf.lfs_file;
7593 curproxy->conf.args.line = curproxy->conf.lfs_line;
7594 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007595 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007596 curproxy->conf.args.file = NULL;
7597 curproxy->conf.args.line = 0;
7598 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007599
Willy Tarreau62a61232013-04-12 18:13:46 +02007600 if (curproxy->conf.uniqueid_format_string) {
7601 curproxy->conf.args.ctx = ARGC_UIF;
7602 curproxy->conf.args.file = curproxy->conf.uif_file;
7603 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007604 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007605 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007606 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007607 curproxy->conf.args.file = NULL;
7608 curproxy->conf.args.line = 0;
7609 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007610
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007611 /* only now we can check if some args remain unresolved.
7612 * This must be done after the users and groups resolution.
7613 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007614 cfgerr += smp_resolve_args(curproxy);
7615 if (!cfgerr)
7616 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007617
Willy Tarreau2738a142006-07-08 17:28:09 +02007618 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007619 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007620 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007621 (!curproxy->timeout.connect ||
7622 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007623 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007624 " | While not properly invalid, you will certainly encounter various problems\n"
7625 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007626 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007627 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007628 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007629 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007630
Willy Tarreau1fa31262007-12-03 00:36:16 +01007631 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7632 * We must still support older configurations, so let's find out whether those
7633 * parameters have been set or must be copied from contimeouts.
7634 */
7635 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007636 if (!curproxy->timeout.tarpit ||
7637 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007638 /* tarpit timeout not set. We search in the following order:
7639 * default.tarpit, curr.connect, default.connect.
7640 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007641 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007642 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007643 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007644 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007645 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007646 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007647 }
7648 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007649 (!curproxy->timeout.queue ||
7650 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007651 /* queue timeout not set. We search in the following order:
7652 * default.queue, curr.connect, default.connect.
7653 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007654 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007655 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007656 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007657 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007658 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007659 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007660 }
7661 }
7662
Willy Tarreau1620ec32011-08-06 17:05:02 +02007663 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007664 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7665 curproxy->check_req = (char *)malloc(curproxy->check_len);
7666 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007667 }
7668
Willy Tarreau215663d2014-06-13 18:30:23 +02007669 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7670 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7671 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7672 proxy_type_str(curproxy), curproxy->id);
7673 err_code |= ERR_WARN;
7674 }
7675
Willy Tarreau193b8c62012-11-22 00:17:38 +01007676 /* ensure that cookie capture length is not too large */
7677 if (curproxy->capture_len >= global.tune.cookie_len) {
7678 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7679 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7680 err_code |= ERR_WARN;
7681 curproxy->capture_len = global.tune.cookie_len - 1;
7682 }
7683
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007684 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007685 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007686 curproxy->req_cap_pool = create_pool("ptrcap",
7687 curproxy->nb_req_cap * sizeof(char *),
7688 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007689 }
7690
7691 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007692 curproxy->rsp_cap_pool = create_pool("ptrcap",
7693 curproxy->nb_rsp_cap * sizeof(char *),
7694 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007695 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007696
Willy Tarreaubaaee002006-06-26 02:48:02 +02007697 /* first, we will invert the servers list order */
7698 newsrv = NULL;
7699 while (curproxy->srv) {
7700 struct server *next;
7701
7702 next = curproxy->srv->next;
7703 curproxy->srv->next = newsrv;
7704 newsrv = curproxy->srv;
7705 if (!next)
7706 break;
7707 curproxy->srv = next;
7708 }
7709
Willy Tarreau17edc812014-01-03 12:14:34 +01007710 /* Check that no server name conflicts. This causes trouble in the stats.
7711 * We only emit a warning for the first conflict affecting each server,
7712 * in order to avoid combinatory explosion if all servers have the same
7713 * name. We do that only for servers which do not have an explicit ID,
7714 * because these IDs were made also for distinguishing them and we don't
7715 * want to annoy people who correctly manage them.
7716 */
7717 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7718 struct server *other_srv;
7719
7720 if (newsrv->puid)
7721 continue;
7722
7723 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7724 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7725 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7726 newsrv->conf.file, newsrv->conf.line,
7727 proxy_type_str(curproxy), curproxy->id,
7728 newsrv->id, other_srv->conf.line);
7729 break;
7730 }
7731 }
7732 }
7733
Willy Tarreaudd701652010-05-25 23:03:02 +02007734 /* assign automatic UIDs to servers which don't have one yet */
7735 next_id = 1;
7736 newsrv = curproxy->srv;
7737 while (newsrv != NULL) {
7738 if (!newsrv->puid) {
7739 /* server ID not set, use automatic numbering with first
7740 * spare entry starting with next_svid.
7741 */
7742 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7743 newsrv->conf.id.key = newsrv->puid = next_id;
7744 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7745 }
7746 next_id++;
7747 newsrv = newsrv->next;
7748 }
7749
Willy Tarreau20697042007-11-15 23:26:18 +01007750 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007751 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007752
Willy Tarreau62c3be22012-01-20 13:12:32 +01007753 /*
7754 * If this server supports a maxconn parameter, it needs a dedicated
7755 * tasks to fill the emptied slots when a connection leaves.
7756 * Also, resolve deferred tracking dependency if needed.
7757 */
7758 newsrv = curproxy->srv;
7759 while (newsrv != NULL) {
7760 if (newsrv->minconn > newsrv->maxconn) {
7761 /* Only 'minconn' was specified, or it was higher than or equal
7762 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7763 * this will avoid further useless expensive computations.
7764 */
7765 newsrv->maxconn = newsrv->minconn;
7766 } else if (newsrv->maxconn && !newsrv->minconn) {
7767 /* minconn was not specified, so we set it to maxconn */
7768 newsrv->minconn = newsrv->maxconn;
7769 }
7770
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007771#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007772 if (newsrv->use_ssl || newsrv->check.use_ssl)
7773 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007774#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007775
Willy Tarreau2f075e92013-12-03 11:11:34 +01007776 /* set the check type on the server */
7777 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7778
Willy Tarreau62c3be22012-01-20 13:12:32 +01007779 if (newsrv->trackit) {
7780 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007781 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007782 char *pname, *sname;
7783
7784 pname = newsrv->trackit;
7785 sname = strrchr(pname, '/');
7786
7787 if (sname)
7788 *sname++ = '\0';
7789 else {
7790 sname = pname;
7791 pname = NULL;
7792 }
7793
7794 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007795 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007796 if (!px) {
7797 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7798 proxy_type_str(curproxy), curproxy->id,
7799 newsrv->id, pname);
7800 cfgerr++;
7801 goto next_srv;
7802 }
7803 } else
7804 px = curproxy;
7805
7806 srv = findserver(px, sname);
7807 if (!srv) {
7808 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7809 proxy_type_str(curproxy), curproxy->id,
7810 newsrv->id, sname);
7811 cfgerr++;
7812 goto next_srv;
7813 }
7814
Willy Tarreau32091232014-05-16 13:52:00 +02007815 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7816 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7817 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007818 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007819 "tracking as it does not have any check nor agent enabled.\n",
7820 proxy_type_str(curproxy), curproxy->id,
7821 newsrv->id, px->id, srv->id);
7822 cfgerr++;
7823 goto next_srv;
7824 }
7825
7826 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7827
7828 if (loop) {
7829 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7830 "belongs to a tracking chain looping back to %s/%s.\n",
7831 proxy_type_str(curproxy), curproxy->id,
7832 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007833 cfgerr++;
7834 goto next_srv;
7835 }
7836
7837 if (curproxy != px &&
7838 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7839 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7840 "tracking: disable-on-404 option inconsistency.\n",
7841 proxy_type_str(curproxy), curproxy->id,
7842 newsrv->id, px->id, srv->id);
7843 cfgerr++;
7844 goto next_srv;
7845 }
7846
7847 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007848 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007849 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007850 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007851 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007852 }
7853
7854 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007855 newsrv->tracknext = srv->trackers;
7856 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007857
7858 free(newsrv->trackit);
7859 newsrv->trackit = NULL;
7860 }
7861 next_srv:
7862 newsrv = newsrv->next;
7863 }
7864
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007865 /* We have to initialize the server lookup mechanism depending
7866 * on what LB algorithm was choosen.
7867 */
7868
7869 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7870 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7871 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007872 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7873 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7874 init_server_map(curproxy);
7875 } else {
7876 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7877 fwrr_init_server_groups(curproxy);
7878 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007879 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007880
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007881 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007882 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7883 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7884 fwlc_init_server_tree(curproxy);
7885 } else {
7886 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7887 fas_init_server_tree(curproxy);
7888 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007889 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007890
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007891 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007892 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7893 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7894 chash_init_server_tree(curproxy);
7895 } else {
7896 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7897 init_server_map(curproxy);
7898 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007899 break;
7900 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007901
7902 if (curproxy->options & PR_O_LOGASAP)
7903 curproxy->to_log &= ~LW_BYTES;
7904
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007905 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007906 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007907 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7908 proxy_type_str(curproxy), curproxy->id);
7909 err_code |= ERR_WARN;
7910 }
7911
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007912 if (curproxy->mode != PR_MODE_HTTP) {
7913 int optnum;
7914
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007915 if (curproxy->uri_auth) {
7916 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7917 proxy_type_str(curproxy), curproxy->id);
7918 err_code |= ERR_WARN;
7919 curproxy->uri_auth = NULL;
7920 }
7921
Willy Tarreau87cf5142011-08-19 22:57:24 +02007922 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007923 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7924 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7925 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007926 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007927 }
7928
7929 if (curproxy->options & PR_O_ORGTO) {
7930 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7931 "originalto", proxy_type_str(curproxy), curproxy->id);
7932 err_code |= ERR_WARN;
7933 curproxy->options &= ~PR_O_ORGTO;
7934 }
7935
7936 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7937 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7938 (curproxy->cap & cfg_opts[optnum].cap) &&
7939 (curproxy->options & cfg_opts[optnum].val)) {
7940 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7941 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7942 err_code |= ERR_WARN;
7943 curproxy->options &= ~cfg_opts[optnum].val;
7944 }
7945 }
7946
7947 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7948 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7949 (curproxy->cap & cfg_opts2[optnum].cap) &&
7950 (curproxy->options2 & cfg_opts2[optnum].val)) {
7951 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7952 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7953 err_code |= ERR_WARN;
7954 curproxy->options2 &= ~cfg_opts2[optnum].val;
7955 }
7956 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007957
Pieter Baauwd551fb52013-05-08 22:49:23 +02007958#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007959 if (curproxy->conn_src.bind_hdr_occ) {
7960 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007961 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007962 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007963 err_code |= ERR_WARN;
7964 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007965#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007966 }
7967
Willy Tarreaubaaee002006-06-26 02:48:02 +02007968 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007969 * ensure that we're not cross-dressing a TCP server into HTTP.
7970 */
7971 newsrv = curproxy->srv;
7972 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007973 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007974 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7975 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007976 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007977 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007978
Willy Tarreau0cec3312011-10-31 13:49:26 +01007979 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7980 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7981 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7982 err_code |= ERR_WARN;
7983 }
7984
Willy Tarreauc93cd162014-05-13 15:54:22 +02007985 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007986 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7987 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7988 err_code |= ERR_WARN;
7989 }
7990
Pieter Baauwd551fb52013-05-08 22:49:23 +02007991#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007992 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7993 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007994 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 +01007995 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007996 err_code |= ERR_WARN;
7997 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007998#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007999 newsrv = newsrv->next;
8000 }
8001
Willy Tarreaue42bd962014-09-16 16:21:19 +02008002 /* check if we have a frontend with "tcp-request content" looking at L7
8003 * with no inspect-delay
8004 */
8005 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8006 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
8007 if (trule->action == TCP_ACT_CAPTURE &&
8008 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
8009 break;
8010 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
8011 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
8012 break;
8013 }
8014
8015 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8016 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8017 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8018 " This means that these rules will randomly find their contents. This can be fixed by"
8019 " setting the tcp-request inspect-delay.\n",
8020 proxy_type_str(curproxy), curproxy->id);
8021 err_code |= ERR_WARN;
8022 }
8023 }
8024
Willy Tarreauc1a21672009-08-16 22:37:44 +02008025 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008026 if (!curproxy->accept)
8027 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008028
Willy Tarreauc1a21672009-08-16 22:37:44 +02008029 if (curproxy->tcp_req.inspect_delay ||
8030 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008031 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008032
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008033 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008034 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008035 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008036 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008037
8038 /* both TCP and HTTP must check switching rules */
8039 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
8040 }
8041
8042 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008043 if (curproxy->tcp_req.inspect_delay ||
8044 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8045 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8046
Emeric Brun97679e72010-09-23 17:56:44 +02008047 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8048 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8049
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008050 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008051 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008052 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008053 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008054
8055 /* If the backend does requires RDP cookie persistence, we have to
8056 * enable the corresponding analyser.
8057 */
8058 if (curproxy->options2 & PR_O2_RDPC_PRST)
8059 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
8060 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008061 }
8062
8063 /***********************************************************/
8064 /* At this point, target names have already been resolved. */
8065 /***********************************************************/
8066
8067 /* Check multi-process mode compatibility */
8068
8069 if (global.nbproc > 1 && global.stats_fe) {
8070 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8071 unsigned long mask;
8072
8073 mask = nbits(global.nbproc);
8074 if (global.stats_fe->bind_proc)
8075 mask &= global.stats_fe->bind_proc;
8076
8077 if (bind_conf->bind_proc)
8078 mask &= bind_conf->bind_proc;
8079
8080 /* stop here if more than one process is used */
8081 if (popcount(mask) > 1)
8082 break;
8083 }
8084 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8085 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");
8086 }
8087 }
8088
8089 /* Make each frontend inherit bind-process from its listeners when not specified. */
8090 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8091 if (curproxy->bind_proc)
8092 continue;
8093
8094 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8095 unsigned long mask;
8096
Willy Tarreaue428b082015-05-04 21:57:58 +02008097 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008098 curproxy->bind_proc |= mask;
8099 }
8100
8101 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008102 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008103 }
8104
8105 if (global.stats_fe) {
8106 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8107 unsigned long mask;
8108
Willy Tarreaue428b082015-05-04 21:57:58 +02008109 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008110 global.stats_fe->bind_proc |= mask;
8111 }
8112 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008113 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008114 }
8115
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008116 /* propagate bindings from frontends to backends. Don't do it if there
8117 * are any fatal errors as we must not call it with unresolved proxies.
8118 */
8119 if (!cfgerr) {
8120 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8121 if (curproxy->cap & PR_CAP_FE)
8122 propagate_processes(curproxy, NULL);
8123 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008124 }
8125
8126 /* Bind each unbound backend to all processes when not specified. */
8127 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8128 if (curproxy->bind_proc)
8129 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008130 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008131 }
8132
8133 /*******************************************************/
8134 /* At this step, all proxies have a non-null bind_proc */
8135 /*******************************************************/
8136
8137 /* perform the final checks before creating tasks */
8138
8139 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8140 struct listener *listener;
8141 unsigned int next_id;
8142 int nbproc;
8143
8144 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008145
Emeric Brunc52962f2012-11-15 18:28:02 +01008146#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008147 /* Configure SSL for each bind line.
8148 * Note: if configuration fails at some point, the ->ctx member
8149 * remains NULL so that listeners can later detach.
8150 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008151 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008152 int alloc_ctx;
8153
Emeric Brunc52962f2012-11-15 18:28:02 +01008154 if (!bind_conf->is_ssl) {
8155 if (bind_conf->default_ctx) {
8156 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8157 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8158 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008159 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008160 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008161 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008162 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008163 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008164 cfgerr++;
8165 continue;
8166 }
8167
Emeric Brun8dc60392014-05-09 13:52:00 +02008168 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008169 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008170 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8171 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");
8172 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008173 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008174 cfgerr++;
8175 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008176 }
8177
Emeric Brunfc0421f2012-09-07 17:30:07 +02008178 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008179 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008180 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008181#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008182
Willy Tarreaue6b98942007-10-29 01:09:36 +01008183 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008184 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008185 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008186 if (!listener->luid) {
8187 /* listener ID not set, use automatic numbering with first
8188 * spare entry starting with next_luid.
8189 */
8190 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8191 listener->conf.id.key = listener->luid = next_id;
8192 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008193 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008194 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008195
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008196 /* enable separate counters */
8197 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8198 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008199 if (!listener->name)
8200 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008201 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008202
Willy Tarreaue6b98942007-10-29 01:09:36 +01008203 if (curproxy->options & PR_O_TCP_NOLING)
8204 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008205 if (!listener->maxconn)
8206 listener->maxconn = curproxy->maxconn;
8207 if (!listener->backlog)
8208 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008209 if (!listener->maxaccept)
8210 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8211
8212 /* we want to have an optimal behaviour on single process mode to
8213 * maximize the work at once, but in multi-process we want to keep
8214 * some fairness between processes, so we target half of the max
8215 * number of events to be balanced over all the processes the proxy
8216 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8217 * used to disable the limit.
8218 */
8219 if (listener->maxaccept > 0) {
8220 if (nbproc > 1)
8221 listener->maxaccept = (listener->maxaccept + 1) / 2;
8222 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8223 }
8224
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008225 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008226 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008227 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008228 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008229
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008230 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8231 listener->options |= LI_O_TCP_RULES;
8232
Willy Tarreaude3041d2010-05-31 10:56:17 +02008233 if (curproxy->mon_mask.s_addr)
8234 listener->options |= LI_O_CHK_MONNET;
8235
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008236 /* smart accept mode is automatic in HTTP mode */
8237 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008238 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008239 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8240 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008241 }
8242
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008243 /* Release unused SSL configs */
8244 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8245 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008246 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008247#ifdef USE_OPENSSL
8248 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008249 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008250 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008251 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008252 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008253 if(bind_conf->keys_ref) {
8254 free(bind_conf->keys_ref->filename);
8255 free(bind_conf->keys_ref->tlskeys);
8256 free(bind_conf->keys_ref);
8257 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008258#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008259 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008260
Willy Tarreau102df612014-05-07 23:56:38 +02008261 if (nbproc > 1) {
8262 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008263 int count, maxproc = 0;
8264
8265 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8266 count = popcount(bind_conf->bind_proc);
8267 if (count > maxproc)
8268 maxproc = count;
8269 }
8270 /* backends have 0, frontends have 1 or more */
8271 if (maxproc != 1)
8272 Warning("Proxy '%s': in multi-process mode, stats will be"
8273 " limited to process assigned to the current request.\n",
8274 curproxy->id);
8275
Willy Tarreau102df612014-05-07 23:56:38 +02008276 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8277 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8278 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008279 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008280 }
Willy Tarreau102df612014-05-07 23:56:38 +02008281 if (curproxy->appsession_name) {
8282 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
8283 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008284 }
Willy Tarreau102df612014-05-07 23:56:38 +02008285 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8286 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8287 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008288 }
8289 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008290
8291 /* create the task associated with the proxy */
8292 curproxy->task = task_new();
8293 if (curproxy->task) {
8294 curproxy->task->context = curproxy;
8295 curproxy->task->process = manage_proxy;
8296 /* no need to queue, it will be done automatically if some
8297 * listener gets limited.
8298 */
8299 curproxy->task->expire = TICK_ETERNITY;
8300 } else {
8301 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8302 curproxy->id);
8303 cfgerr++;
8304 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008305 }
8306
Willy Tarreaufbb78422011-06-05 15:38:35 +02008307 /* automatically compute fullconn if not set. We must not do it in the
8308 * loop above because cross-references are not yet fully resolved.
8309 */
8310 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8311 /* If <fullconn> is not set, let's set it to 10% of the sum of
8312 * the possible incoming frontend's maxconns.
8313 */
8314 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8315 struct proxy *fe;
8316 int total = 0;
8317
8318 /* sum up the number of maxconns of frontends which
8319 * reference this backend at least once or which are
8320 * the same one ('listen').
8321 */
8322 for (fe = proxy; fe; fe = fe->next) {
8323 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008324 int found = 0;
8325
8326 if (!(fe->cap & PR_CAP_FE))
8327 continue;
8328
8329 if (fe == curproxy) /* we're on a "listen" instance */
8330 found = 1;
8331
8332 if (fe->defbe.be == curproxy) /* "default_backend" */
8333 found = 1;
8334
8335 /* check if a "use_backend" rule matches */
8336 if (!found) {
8337 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008338 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008339 found = 1;
8340 break;
8341 }
8342 }
8343 }
8344
Willy Tarreaufbb78422011-06-05 15:38:35 +02008345 /* now we've checked all possible ways to reference a backend
8346 * from a frontend.
8347 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008348 if (!found)
8349 continue;
8350 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008351 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008352 /* we have the sum of the maxconns in <total>. We only
8353 * keep 10% of that sum to set the default fullconn, with
8354 * a hard minimum of 1 (to avoid a divide by zero).
8355 */
8356 curproxy->fullconn = (total + 9) / 10;
8357 if (!curproxy->fullconn)
8358 curproxy->fullconn = 1;
8359 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008360 }
8361
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008362 /*
8363 * Recount currently required checks.
8364 */
8365
8366 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8367 int optnum;
8368
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008369 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8370 if (curproxy->options & cfg_opts[optnum].val)
8371 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008372
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008373 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8374 if (curproxy->options2 & cfg_opts2[optnum].val)
8375 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008376 }
8377
Willy Tarreau0fca4832015-05-01 19:12:05 +02008378 /* compute the required process bindings for the peers */
8379 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8380 if (curproxy->table.peers.p)
8381 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8382
Willy Tarreau122541c2011-09-07 21:24:49 +02008383 if (peers) {
8384 struct peers *curpeers = peers, **last;
8385 struct peer *p, *pb;
8386
Willy Tarreau1e273012015-05-01 19:15:17 +02008387 /* Remove all peers sections which don't have a valid listener,
8388 * which are not used by any table, or which are bound to more
8389 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008390 */
8391 last = &peers;
8392 while (*last) {
8393 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008394
8395 if (curpeers->state == PR_STSTOPPED) {
8396 /* the "disabled" keyword was present */
8397 if (curpeers->peers_fe)
8398 stop_proxy(curpeers->peers_fe);
8399 curpeers->peers_fe = NULL;
8400 }
8401 else if (!curpeers->peers_fe) {
8402 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8403 curpeers->id, localpeer);
8404 }
Willy Tarreau1e273012015-05-01 19:15:17 +02008405 else if (popcount(curpeers->peers_fe->bind_proc) != 1) {
8406 /* either it's totally stopped or too much used */
8407 if (curpeers->peers_fe->bind_proc) {
8408 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008409 "running in different processes (%d different ones). "
8410 "Check global.nbproc and all tables' bind-process "
8411 "settings.\n", curpeers->id, popcount(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008412 cfgerr++;
8413 }
8414 stop_proxy(curpeers->peers_fe);
8415 curpeers->peers_fe = NULL;
8416 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008417 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008418 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008419 last = &curpeers->next;
8420 continue;
8421 }
8422
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008423 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008424 p = curpeers->remote;
8425 while (p) {
8426 pb = p->next;
8427 free(p->id);
8428 free(p);
8429 p = pb;
8430 }
8431
8432 /* Destroy and unlink this curpeers section.
8433 * Note: curpeers is backed up into *last.
8434 */
8435 free(curpeers->id);
8436 curpeers = curpeers->next;
8437 free(*last);
8438 *last = curpeers;
8439 }
8440 }
8441
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008442 /* initialize stick-tables on backend capable proxies. This must not
8443 * be done earlier because the data size may be discovered while parsing
8444 * other proxies.
8445 */
8446 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8447 if (curproxy->state == PR_STSTOPPED)
8448 continue;
8449
8450 if (!stktable_init(&curproxy->table)) {
8451 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8452 cfgerr++;
8453 }
8454 }
8455
Simon Horman0d16a402015-01-30 11:22:58 +09008456 if (mailers) {
8457 struct mailers *curmailers = mailers, **last;
8458 struct mailer *m, *mb;
8459
8460 /* Remove all mailers sections which don't have a valid listener.
8461 * This can happen when a mailers section is never referenced.
8462 */
8463 last = &mailers;
8464 while (*last) {
8465 curmailers = *last;
8466 if (curmailers->users) {
8467 last = &curmailers->next;
8468 continue;
8469 }
8470
8471 Warning("Removing incomplete section 'mailers %s'.\n",
8472 curmailers->id);
8473
8474 m = curmailers->mailer_list;
8475 while (m) {
8476 mb = m->next;
8477 free(m->id);
8478 free(m);
8479 m = mb;
8480 }
8481
8482 /* Destroy and unlink this curmailers section.
8483 * Note: curmailers is backed up into *last.
8484 */
8485 free(curmailers->id);
8486 curmailers = curmailers->next;
8487 free(*last);
8488 *last = curmailers;
8489 }
8490 }
8491
Willy Tarreau34eb6712011-10-24 18:15:04 +02008492 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008493 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008494 MEM_F_SHARED);
8495
Willy Tarreaubb925012009-07-23 13:36:36 +02008496 if (cfgerr > 0)
8497 err_code |= ERR_ALERT | ERR_FATAL;
8498 out:
8499 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008500}
8501
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008502/*
8503 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8504 * parsing sessions.
8505 */
8506void cfg_register_keywords(struct cfg_kw_list *kwl)
8507{
8508 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8509}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008510
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008511/*
8512 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8513 */
8514void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8515{
8516 LIST_DEL(&kwl->list);
8517 LIST_INIT(&kwl->list);
8518}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008519
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008520/* this function register new section in the haproxy configuration file.
8521 * <section_name> is the name of this new section and <section_parser>
8522 * is the called parser. If two section declaration have the same name,
8523 * only the first declared is used.
8524 */
8525int cfg_register_section(char *section_name,
8526 int (*section_parser)(const char *, int, char **, int))
8527{
8528 struct cfg_section *cs;
8529
8530 cs = calloc(1, sizeof(*cs));
8531 if (!cs) {
8532 Alert("register section '%s': out of memory.\n", section_name);
8533 return 0;
8534 }
8535
8536 cs->section_name = section_name;
8537 cs->section_parser = section_parser;
8538
8539 LIST_ADDQ(&sections, &cs->list);
8540
8541 return 1;
8542}
8543
Willy Tarreaubaaee002006-06-26 02:48:02 +02008544/*
8545 * Local variables:
8546 * c-indent-level: 8
8547 * c-basic-offset: 8
8548 * End:
8549 */