blob: bb3118859a6c422ff0ca9f818517ea70c575d827 [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 Gacognef46cd6e2014-06-12 14:58:40 +0200756 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200757 if (alertif_too_many_args(1, file, linenum, args, &err_code))
758 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200759 if (*(args[1]) == 0) {
760 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
761 err_code |= ERR_ALERT | ERR_FATAL;
762 goto out;
763 }
764 global.tune.ssl_default_dh_param = atol(args[1]);
765 if (global.tune.ssl_default_dh_param < 1024) {
766 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
769 }
770 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200771#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100772 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200773 if (alertif_too_many_args(1, file, linenum, args, &err_code))
774 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100775 if (*(args[1]) == 0) {
776 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
777 err_code |= ERR_ALERT | ERR_FATAL;
778 goto out;
779 }
780 global.tune.buf_limit = atol(args[1]);
781 if (global.tune.buf_limit) {
782 if (global.tune.buf_limit < 3)
783 global.tune.buf_limit = 3;
784 if (global.tune.buf_limit <= global.tune.reserved_bufs)
785 global.tune.buf_limit = global.tune.reserved_bufs + 1;
786 }
787 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100788 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200789 if (alertif_too_many_args(1, file, linenum, args, &err_code))
790 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100791 if (*(args[1]) == 0) {
792 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
793 err_code |= ERR_ALERT | ERR_FATAL;
794 goto out;
795 }
796 global.tune.reserved_bufs = atol(args[1]);
797 if (global.tune.reserved_bufs < 2)
798 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100799 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
800 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100801 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200802 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200803 if (alertif_too_many_args(1, file, linenum, args, &err_code))
804 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200805 if (*(args[1]) == 0) {
806 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
809 }
810 global.tune.bufsize = atol(args[1]);
811 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
812 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100813 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100814 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200815 }
816 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200817 if (alertif_too_many_args(1, file, linenum, args, &err_code))
818 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200819 if (*(args[1]) == 0) {
820 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
821 err_code |= ERR_ALERT | ERR_FATAL;
822 goto out;
823 }
824 global.tune.maxrewrite = atol(args[1]);
825 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
826 global.tune.maxrewrite = global.tune.bufsize / 2;
827 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100828 else if (!strcmp(args[0], "tune.idletimer")) {
829 unsigned int idle;
830 const char *res;
831
William Lallemand1a748ae2015-05-19 16:37:23 +0200832 if (alertif_too_many_args(1, file, linenum, args, &err_code))
833 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100834 if (*(args[1]) == 0) {
835 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
836 err_code |= ERR_ALERT | ERR_FATAL;
837 goto out;
838 }
839
840 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
841 if (res) {
842 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
843 file, linenum, *res, args[0]);
844 err_code |= ERR_ALERT | ERR_FATAL;
845 goto out;
846 }
847
848 if (idle > 65535) {
849 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
850 err_code |= ERR_ALERT | ERR_FATAL;
851 goto out;
852 }
853 global.tune.idle_timer = idle;
854 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100855 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200856 if (alertif_too_many_args(1, file, linenum, args, &err_code))
857 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100858 if (global.tune.client_rcvbuf != 0) {
859 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
860 err_code |= ERR_ALERT;
861 goto out;
862 }
863 if (*(args[1]) == 0) {
864 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
865 err_code |= ERR_ALERT | ERR_FATAL;
866 goto out;
867 }
868 global.tune.client_rcvbuf = atol(args[1]);
869 }
870 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200871 if (alertif_too_many_args(1, file, linenum, args, &err_code))
872 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100873 if (global.tune.server_rcvbuf != 0) {
874 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
875 err_code |= ERR_ALERT;
876 goto out;
877 }
878 if (*(args[1]) == 0) {
879 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
880 err_code |= ERR_ALERT | ERR_FATAL;
881 goto out;
882 }
883 global.tune.server_rcvbuf = atol(args[1]);
884 }
885 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200886 if (alertif_too_many_args(1, file, linenum, args, &err_code))
887 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100888 if (global.tune.client_sndbuf != 0) {
889 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
890 err_code |= ERR_ALERT;
891 goto out;
892 }
893 if (*(args[1]) == 0) {
894 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
895 err_code |= ERR_ALERT | ERR_FATAL;
896 goto out;
897 }
898 global.tune.client_sndbuf = atol(args[1]);
899 }
900 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200901 if (alertif_too_many_args(1, file, linenum, args, &err_code))
902 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100903 if (global.tune.server_sndbuf != 0) {
904 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
905 err_code |= ERR_ALERT;
906 goto out;
907 }
908 if (*(args[1]) == 0) {
909 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
910 err_code |= ERR_ALERT | ERR_FATAL;
911 goto out;
912 }
913 global.tune.server_sndbuf = atol(args[1]);
914 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200915 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200916 if (alertif_too_many_args(1, file, linenum, args, &err_code))
917 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200918 if (*(args[1]) == 0) {
919 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
920 err_code |= ERR_ALERT | ERR_FATAL;
921 goto out;
922 }
923 global.tune.pipesize = atol(args[1]);
924 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100925 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200926 if (alertif_too_many_args(1, file, linenum, args, &err_code))
927 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100928 if (*(args[1]) == 0) {
929 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
930 err_code |= ERR_ALERT | ERR_FATAL;
931 goto out;
932 }
933 global.tune.cookie_len = atol(args[1]) + 1;
934 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200935 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200936 if (alertif_too_many_args(1, file, linenum, args, &err_code))
937 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
942 }
943 global.tune.max_http_hdr = atol(args[1]);
944 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100945 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
946#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200947 if (alertif_too_many_args(1, file, linenum, args, &err_code))
948 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100949 if (*args[1]) {
950 global.tune.zlibmemlevel = atoi(args[1]);
951 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
952 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
953 file, linenum, args[0]);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
956 }
957 } else {
958 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
959 file, linenum, args[0]);
960 err_code |= ERR_ALERT | ERR_FATAL;
961 goto out;
962 }
963#else
964 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
965 err_code |= ERR_ALERT | ERR_FATAL;
966 goto out;
967#endif
968 }
969 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
970#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200971 if (alertif_too_many_args(1, file, linenum, args, &err_code))
972 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100973 if (*args[1]) {
974 global.tune.zlibwindowsize = atoi(args[1]);
975 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
976 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
977 file, linenum, args[0]);
978 err_code |= ERR_ALERT | ERR_FATAL;
979 goto out;
980 }
981 } else {
982 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
983 file, linenum, args[0]);
984 err_code |= ERR_ALERT | ERR_FATAL;
985 goto out;
986 }
987#else
988 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
989 err_code |= ERR_ALERT | ERR_FATAL;
990 goto out;
991#endif
992 }
William Lallemandf3747832012-11-09 12:33:10 +0100993 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200994 if (alertif_too_many_args(1, file, linenum, args, &err_code))
995 goto out;
William Lallemandf3747832012-11-09 12:33:10 +0100996 if (*args[1]) {
997 global.tune.comp_maxlevel = atoi(args[1]);
998 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
999 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1000 file, linenum, args[0]);
1001 err_code |= ERR_ALERT | ERR_FATAL;
1002 goto out;
1003 }
1004 } else {
1005 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1006 file, linenum, args[0]);
1007 err_code |= ERR_ALERT | ERR_FATAL;
1008 goto out;
1009 }
1010 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001011 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1012 if (*args[1]) {
1013 global.tune.pattern_cache = atoi(args[1]);
1014 if (global.tune.pattern_cache < 0) {
1015 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1016 file, linenum, args[0]);
1017 err_code |= ERR_ALERT | ERR_FATAL;
1018 goto out;
1019 }
1020 } else {
1021 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1022 file, linenum, args[0]);
1023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
1025 }
1026 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001027 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001028 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001030 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001031 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001032 err_code |= ERR_ALERT;
1033 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001034 }
1035 if (*(args[1]) == 0) {
1036 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001037 err_code |= ERR_ALERT | ERR_FATAL;
1038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001039 }
1040 global.uid = atol(args[1]);
1041 }
1042 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001043 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001046 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001047 err_code |= ERR_ALERT;
1048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 }
1050 if (*(args[1]) == 0) {
1051 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001052 err_code |= ERR_ALERT | ERR_FATAL;
1053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054 }
1055 global.gid = atol(args[1]);
1056 }
Simon Horman98637e52014-06-20 12:30:16 +09001057 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001058 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1059 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001060 global.external_check = 1;
1061 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001062 /* user/group name handling */
1063 else if (!strcmp(args[0], "user")) {
1064 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001065 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1066 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001067 if (global.uid != 0) {
1068 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001069 err_code |= ERR_ALERT;
1070 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001071 }
1072 errno = 0;
1073 ha_user = getpwnam(args[1]);
1074 if (ha_user != NULL) {
1075 global.uid = (int)ha_user->pw_uid;
1076 }
1077 else {
1078 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 +02001079 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001080 }
1081 }
1082 else if (!strcmp(args[0], "group")) {
1083 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001084 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1085 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001086 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001087 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001088 err_code |= ERR_ALERT;
1089 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001090 }
1091 errno = 0;
1092 ha_group = getgrnam(args[1]);
1093 if (ha_group != NULL) {
1094 global.gid = (int)ha_group->gr_gid;
1095 }
1096 else {
1097 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 +02001098 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001099 }
1100 }
1101 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001103 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001105 if (*(args[1]) == 0) {
1106 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001107 err_code |= ERR_ALERT | ERR_FATAL;
1108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001109 }
1110 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001111 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1112 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1113 file, linenum, args[0], LONGBITS, global.nbproc);
1114 err_code |= ERR_ALERT | ERR_FATAL;
1115 goto out;
1116 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001117 }
1118 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001119 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001121 if (global.maxconn != 0) {
1122 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001123 err_code |= ERR_ALERT;
1124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 }
1126 if (*(args[1]) == 0) {
1127 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001128 err_code |= ERR_ALERT | ERR_FATAL;
1129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001130 }
1131 global.maxconn = atol(args[1]);
1132#ifdef SYSTEM_MAXCONN
1133 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1134 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);
1135 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001137 }
1138#endif /* SYSTEM_MAXCONN */
1139 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001140 else if (!strcmp(args[0], "maxsslconn")) {
1141#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001142 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1143 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001144 if (*(args[1]) == 0) {
1145 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1146 err_code |= ERR_ALERT | ERR_FATAL;
1147 goto out;
1148 }
1149 global.maxsslconn = atol(args[1]);
1150#else
Emeric Brun0914df82012-10-02 18:45:42 +02001151 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1152 err_code |= ERR_ALERT | ERR_FATAL;
1153 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001154#endif
1155 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001156 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1157#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001158 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1159 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001160 if (*(args[1]) == 0) {
1161 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1162 err_code |= ERR_ALERT | ERR_FATAL;
1163 goto out;
1164 }
1165 free(global.listen_default_ciphers);
1166 global.listen_default_ciphers = strdup(args[1]);
1167#else
1168 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1169 err_code |= ERR_ALERT | ERR_FATAL;
1170 goto out;
1171#endif
1172 }
1173 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1174#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001175 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1176 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001177 if (*(args[1]) == 0) {
1178 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1179 err_code |= ERR_ALERT | ERR_FATAL;
1180 goto out;
1181 }
1182 free(global.connect_default_ciphers);
1183 global.connect_default_ciphers = strdup(args[1]);
1184#else
1185 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1186 err_code |= ERR_ALERT | ERR_FATAL;
1187 goto out;
1188#endif
1189 }
Emeric Brun850efd52014-01-29 12:24:34 +01001190 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001191 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1192 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001193 if (*(args[1]) == 0) {
1194 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1195 err_code |= ERR_ALERT | ERR_FATAL;
1196 goto out;
1197 }
1198 if (strcmp(args[1],"none") == 0)
1199 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1200 else if (strcmp(args[1],"required") == 0)
1201 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1202 else {
1203 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1204 err_code |= ERR_ALERT | ERR_FATAL;
1205 goto out;
1206 }
1207 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001208 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001209 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1210 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001211 if (global.cps_lim != 0) {
1212 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1213 err_code |= ERR_ALERT;
1214 goto out;
1215 }
1216 if (*(args[1]) == 0) {
1217 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1218 err_code |= ERR_ALERT | ERR_FATAL;
1219 goto out;
1220 }
1221 global.cps_lim = atol(args[1]);
1222 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001223 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001224 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1225 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001226 if (global.sps_lim != 0) {
1227 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1228 err_code |= ERR_ALERT;
1229 goto out;
1230 }
1231 if (*(args[1]) == 0) {
1232 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1233 err_code |= ERR_ALERT | ERR_FATAL;
1234 goto out;
1235 }
1236 global.sps_lim = atol(args[1]);
1237 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001238 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001239 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1240 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001241 if (global.ssl_lim != 0) {
1242 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1243 err_code |= ERR_ALERT;
1244 goto out;
1245 }
1246 if (*(args[1]) == 0) {
1247 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1248 err_code |= ERR_ALERT | ERR_FATAL;
1249 goto out;
1250 }
1251 global.ssl_lim = atol(args[1]);
1252 }
William Lallemandd85f9172012-11-09 17:05:39 +01001253 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001254 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1255 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001256 if (*(args[1]) == 0) {
1257 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1258 err_code |= ERR_ALERT | ERR_FATAL;
1259 goto out;
1260 }
1261 global.comp_rate_lim = atoi(args[1]) * 1024;
1262 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001263 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001264 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1265 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001266 if (global.maxpipes != 0) {
1267 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001268 err_code |= ERR_ALERT;
1269 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001270 }
1271 if (*(args[1]) == 0) {
1272 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001273 err_code |= ERR_ALERT | ERR_FATAL;
1274 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001275 }
1276 global.maxpipes = atol(args[1]);
1277 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001278 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001279 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1280 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001281 if (*(args[1]) == 0) {
1282 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1283 err_code |= ERR_ALERT | ERR_FATAL;
1284 goto out;
1285 }
William Lallemande3a7d992012-11-20 11:25:20 +01001286 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001287 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001288 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001289 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1290 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001291 if (*(args[1]) == 0) {
1292 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1293 err_code |= ERR_ALERT | ERR_FATAL;
1294 goto out;
1295 }
1296 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001297 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001298 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1299 err_code |= ERR_ALERT | ERR_FATAL;
1300 goto out;
1301 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001302 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001303
Willy Tarreaubaaee002006-06-26 02:48:02 +02001304 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001305 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001307 if (global.rlimit_nofile != 0) {
1308 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001309 err_code |= ERR_ALERT;
1310 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001311 }
1312 if (*(args[1]) == 0) {
1313 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001314 err_code |= ERR_ALERT | ERR_FATAL;
1315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001316 }
1317 global.rlimit_nofile = atol(args[1]);
1318 }
1319 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001320 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001322 if (global.chroot != NULL) {
1323 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001324 err_code |= ERR_ALERT;
1325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001326 }
1327 if (*(args[1]) == 0) {
1328 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001329 err_code |= ERR_ALERT | ERR_FATAL;
1330 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001331 }
1332 global.chroot = strdup(args[1]);
1333 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001334 else if (!strcmp(args[0], "description")) {
1335 int i, len=0;
1336 char *d;
1337
1338 if (!*args[1]) {
1339 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1340 file, linenum, args[0]);
1341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
1343 }
1344
Willy Tarreau348acfe2014-04-14 15:00:39 +02001345 for (i = 1; *args[i]; i++)
1346 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001347
1348 if (global.desc)
1349 free(global.desc);
1350
1351 global.desc = d = (char *)calloc(1, len);
1352
Willy Tarreau348acfe2014-04-14 15:00:39 +02001353 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1354 for (i = 2; *args[i]; i++)
1355 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001356 }
1357 else if (!strcmp(args[0], "node")) {
1358 int i;
1359 char c;
1360
William Lallemand1a748ae2015-05-19 16:37:23 +02001361 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1362 goto out;
1363
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001364 for (i=0; args[1][i]; i++) {
1365 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001366 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1367 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001368 break;
1369 }
1370
1371 if (!i || args[1][i]) {
1372 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1373 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1374 file, linenum, args[0]);
1375 err_code |= ERR_ALERT | ERR_FATAL;
1376 goto out;
1377 }
1378
1379 if (global.node)
1380 free(global.node);
1381
1382 global.node = strdup(args[1]);
1383 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001385 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001387 if (global.pidfile != NULL) {
1388 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001389 err_code |= ERR_ALERT;
1390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391 }
1392 if (*(args[1]) == 0) {
1393 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001394 err_code |= ERR_ALERT | ERR_FATAL;
1395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001396 }
1397 global.pidfile = strdup(args[1]);
1398 }
Emeric Bruned760922010-10-22 17:59:25 +02001399 else if (!strcmp(args[0], "unix-bind")) {
1400 int cur_arg = 1;
1401 while (*(args[cur_arg])) {
1402 if (!strcmp(args[cur_arg], "prefix")) {
1403 if (global.unix_bind.prefix != NULL) {
1404 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1405 err_code |= ERR_ALERT;
1406 cur_arg += 2;
1407 continue;
1408 }
1409
1410 if (*(args[cur_arg+1]) == 0) {
1411 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1412 err_code |= ERR_ALERT | ERR_FATAL;
1413 goto out;
1414 }
1415 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1416 cur_arg += 2;
1417 continue;
1418 }
1419
1420 if (!strcmp(args[cur_arg], "mode")) {
1421
1422 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1423 cur_arg += 2;
1424 continue;
1425 }
1426
1427 if (!strcmp(args[cur_arg], "uid")) {
1428
1429 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1430 cur_arg += 2;
1431 continue;
1432 }
1433
1434 if (!strcmp(args[cur_arg], "gid")) {
1435
1436 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1437 cur_arg += 2;
1438 continue;
1439 }
1440
1441 if (!strcmp(args[cur_arg], "user")) {
1442 struct passwd *user;
1443
1444 user = getpwnam(args[cur_arg + 1]);
1445 if (!user) {
1446 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1447 file, linenum, args[0], args[cur_arg + 1 ]);
1448 err_code |= ERR_ALERT | ERR_FATAL;
1449 goto out;
1450 }
1451
1452 global.unix_bind.ux.uid = user->pw_uid;
1453 cur_arg += 2;
1454 continue;
1455 }
1456
1457 if (!strcmp(args[cur_arg], "group")) {
1458 struct group *group;
1459
1460 group = getgrnam(args[cur_arg + 1]);
1461 if (!group) {
1462 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1463 file, linenum, args[0], args[cur_arg + 1 ]);
1464 err_code |= ERR_ALERT | ERR_FATAL;
1465 goto out;
1466 }
1467
1468 global.unix_bind.ux.gid = group->gr_gid;
1469 cur_arg += 2;
1470 continue;
1471 }
1472
Willy Tarreaub48f9582011-09-05 01:17:06 +02001473 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001474 file, linenum, args[0]);
1475 err_code |= ERR_ALERT | ERR_FATAL;
1476 goto out;
1477 }
1478 }
William Lallemand0f99e342011-10-12 17:50:54 +02001479 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1480 /* delete previous herited or defined syslog servers */
1481 struct logsrv *back;
1482 struct logsrv *tmp;
1483
1484 if (*(args[1]) != 0) {
1485 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1486 err_code |= ERR_ALERT | ERR_FATAL;
1487 goto out;
1488 }
1489
1490 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1491 LIST_DEL(&tmp->list);
1492 free(tmp);
1493 }
1494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001495 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001496 struct sockaddr_storage *sk;
1497 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001498 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001499 int arg = 0;
1500 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001501
William Lallemand1a748ae2015-05-19 16:37:23 +02001502 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1503 goto out;
1504
Willy Tarreaubaaee002006-06-26 02:48:02 +02001505 if (*(args[1]) == 0 || *(args[2]) == 0) {
1506 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001507 err_code |= ERR_ALERT | ERR_FATAL;
1508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001509 }
William Lallemand0f99e342011-10-12 17:50:54 +02001510
1511 logsrv = calloc(1, sizeof(struct logsrv));
1512
Willy Tarreau18324f52014-06-27 18:10:07 +02001513 /* just after the address, a length may be specified */
1514 if (strcmp(args[arg+2], "len") == 0) {
1515 len = atoi(args[arg+3]);
1516 if (len < 80 || len > 65535) {
1517 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1518 file, linenum, args[arg+3]);
1519 err_code |= ERR_ALERT | ERR_FATAL;
1520 goto out;
1521 }
1522 logsrv->maxlen = len;
1523
1524 /* skip these two args */
1525 arg += 2;
1526 }
1527 else
1528 logsrv->maxlen = MAX_SYSLOG_LEN;
1529
1530 if (logsrv->maxlen > global.max_syslog_len) {
1531 global.max_syslog_len = logsrv->maxlen;
1532 logline = realloc(logline, global.max_syslog_len + 1);
1533 }
1534
William Lallemand1a748ae2015-05-19 16:37:23 +02001535 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1536 goto out;
1537
Willy Tarreau18324f52014-06-27 18:10:07 +02001538 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001539 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001540 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001541 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001542 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001543 }
1544
William Lallemand0f99e342011-10-12 17:50:54 +02001545 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001546 if (*(args[arg+3])) {
1547 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001548 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001549 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001550 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001551 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001552 }
1553 }
1554
William Lallemand0f99e342011-10-12 17:50:54 +02001555 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001556 if (*(args[arg+4])) {
1557 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001558 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001559 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001560 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001561 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001562 }
1563 }
1564
Willy Tarreau902636f2013-03-10 19:44:48 +01001565 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001566 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001567 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001568 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001569 free(logsrv);
1570 goto out;
1571 }
1572 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001573
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001574 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001575 if (port1 != port2) {
1576 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1577 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001578 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001579 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001580 goto out;
1581 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001582
William Lallemand0f99e342011-10-12 17:50:54 +02001583 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001584 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001585 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587
William Lallemand0f99e342011-10-12 17:50:54 +02001588 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001589 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001590 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1591 char *name;
1592 int len;
1593
1594 if (global.log_send_hostname != NULL) {
1595 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1596 err_code |= ERR_ALERT;
1597 goto out;
1598 }
1599
1600 if (*(args[1]))
1601 name = args[1];
1602 else
1603 name = hostname;
1604
1605 len = strlen(name);
1606
1607 /* We'll add a space after the name to respect the log format */
1608 free(global.log_send_hostname);
1609 global.log_send_hostname = malloc(len + 2);
1610 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1611 }
Kevinm48936af2010-12-22 16:08:21 +00001612 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001613 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1614 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001615 if (*(args[1]) == 0) {
1616 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1617 err_code |= ERR_ALERT | ERR_FATAL;
1618 goto out;
1619 }
1620 free(global.log_tag);
1621 global.log_tag = strdup(args[1]);
1622 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001623 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001624 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1625 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001626 if (global.spread_checks != 0) {
1627 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001628 err_code |= ERR_ALERT;
1629 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001630 }
1631 if (*(args[1]) == 0) {
1632 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001633 err_code |= ERR_ALERT | ERR_FATAL;
1634 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001635 }
1636 global.spread_checks = atol(args[1]);
1637 if (global.spread_checks < 0 || global.spread_checks > 50) {
1638 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001639 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001640 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001641 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001642 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1643 const char *err;
1644 unsigned int val;
1645
William Lallemand1a748ae2015-05-19 16:37:23 +02001646 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1647 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001648 if (*(args[1]) == 0) {
1649 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1650 err_code |= ERR_ALERT | ERR_FATAL;
1651 goto out;
1652 }
1653
1654 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1655 if (err) {
1656 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1657 err_code |= ERR_ALERT | ERR_FATAL;
1658 }
1659 global.max_spread_checks = val;
1660 if (global.max_spread_checks < 0) {
1661 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1662 err_code |= ERR_ALERT | ERR_FATAL;
1663 }
1664 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001665 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1666#ifdef USE_CPU_AFFINITY
1667 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001668 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001669 unsigned long cpus = 0;
1670
1671 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001672 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001673 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001674 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001675 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001676 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001677 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001678 proc = atol(args[1]);
1679 if (proc >= 1 && proc <= LONGBITS)
1680 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001681 }
1682
1683 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001684 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",
1685 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001686 err_code |= ERR_ALERT | ERR_FATAL;
1687 goto out;
1688 }
1689
1690 cur_arg = 2;
1691 while (*args[cur_arg]) {
1692 unsigned int low, high;
1693
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001694 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001695 char *dash = strchr(args[cur_arg], '-');
1696
1697 low = high = str2uic(args[cur_arg]);
1698 if (dash)
1699 high = str2uic(dash + 1);
1700
1701 if (high < low) {
1702 unsigned int swap = low;
1703 low = high;
1704 high = swap;
1705 }
1706
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001707 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001708 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001709 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001710 err_code |= ERR_ALERT | ERR_FATAL;
1711 goto out;
1712 }
1713
1714 while (low <= high)
1715 cpus |= 1UL << low++;
1716 }
1717 else {
1718 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1719 file, linenum, args[0], args[cur_arg]);
1720 err_code |= ERR_ALERT | ERR_FATAL;
1721 goto out;
1722 }
1723 cur_arg++;
1724 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001725 for (i = 0; i < LONGBITS; i++)
1726 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001727 global.cpu_map[i] = cpus;
1728#else
1729 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1730 err_code |= ERR_ALERT | ERR_FATAL;
1731 goto out;
1732#endif
1733 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001734 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001735 struct cfg_kw_list *kwl;
1736 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001737 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001738
1739 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1740 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1741 if (kwl->kw[index].section != CFG_GLOBAL)
1742 continue;
1743 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001744 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001745 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001746 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001747 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001748 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001749 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001750 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001751 err_code |= ERR_WARN;
1752 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001753 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001754 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001755 }
1756 }
1757 }
1758
Willy Tarreaubaaee002006-06-26 02:48:02 +02001759 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001760 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001761 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001762
Willy Tarreau058e9072009-07-20 09:30:05 +02001763 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001764 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001765 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001766}
1767
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001768void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001769{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001770 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001771 defproxy.mode = PR_MODE_TCP;
1772 defproxy.state = PR_STNEW;
1773 defproxy.maxconn = cfg_maxpconn;
1774 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001775 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001776
Simon Horman66183002013-02-23 10:16:43 +09001777 defproxy.defsrv.check.inter = DEF_CHKINTR;
1778 defproxy.defsrv.check.fastinter = 0;
1779 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001780 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1781 defproxy.defsrv.agent.fastinter = 0;
1782 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001783 defproxy.defsrv.check.rise = DEF_RISETIME;
1784 defproxy.defsrv.check.fall = DEF_FALLTIME;
1785 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1786 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001787 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001788 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001789 defproxy.defsrv.maxqueue = 0;
1790 defproxy.defsrv.minconn = 0;
1791 defproxy.defsrv.maxconn = 0;
1792 defproxy.defsrv.slowstart = 0;
1793 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1794 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1795 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001796
1797 defproxy.email_alert.level = LOG_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001798}
1799
Willy Tarreauade5ec42010-01-28 19:33:49 +01001800
Willy Tarreau63af98d2014-05-18 08:11:41 +02001801/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1802 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1803 * ERR_FATAL in case of error.
1804 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001805static int create_cond_regex_rule(const char *file, int line,
1806 struct proxy *px, int dir, int action, int flags,
1807 const char *cmd, const char *reg, const char *repl,
1808 const char **cond_start)
1809{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001810 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001811 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001812 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001813 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001814 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001815 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001816 int cs;
1817 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001818
1819 if (px == &defproxy) {
1820 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001821 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001822 goto err;
1823 }
1824
1825 if (*reg == 0) {
1826 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001827 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001828 goto err;
1829 }
1830
1831 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001832 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001833
Willy Tarreau5321c422010-01-28 20:35:13 +01001834 if (cond_start &&
1835 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001836 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1837 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1838 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001839 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001840 goto err;
1841 }
1842 }
1843 else if (cond_start && **cond_start) {
1844 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1845 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001846 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001847 goto err;
1848 }
1849
Willy Tarreau63af98d2014-05-18 08:11:41 +02001850 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001851 (dir == SMP_OPT_DIR_REQ) ?
1852 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1853 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1854 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001855
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001856 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001857 if (!preg) {
1858 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001859 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001860 goto err;
1861 }
1862
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001863 cs = !(flags & REG_ICASE);
1864 cap = !(flags & REG_NOSUB);
1865 error = NULL;
1866 if (!regex_comp(reg, preg, cs, cap, &error)) {
1867 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1868 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001869 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001870 goto err;
1871 }
1872
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001873 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001874 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001875 if (repl && err) {
1876 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1877 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001878 ret_code |= ERR_ALERT | ERR_FATAL;
1879 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001880 }
1881
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001882 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001883 ret_code |= ERR_WARN;
1884
1885 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001886
Willy Tarreau63af98d2014-05-18 08:11:41 +02001887 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001888 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001889 err:
1890 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001891 free(errmsg);
1892 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001893}
1894
Willy Tarreaubaaee002006-06-26 02:48:02 +02001895/*
William Lallemand51097192015-04-14 16:35:22 +02001896 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001897 * Returns the error code, 0 if OK, or any combination of :
1898 * - ERR_ABORT: must abort ASAP
1899 * - ERR_FATAL: we can continue parsing but not start the service
1900 * - ERR_WARN: a warning has been emitted
1901 * - ERR_ALERT: an alert has been emitted
1902 * Only the two first ones can stop processing, the two others are just
1903 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001904 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001905int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1906{
1907 static struct peers *curpeers = NULL;
1908 struct peer *newpeer = NULL;
1909 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001910 struct bind_conf *bind_conf;
1911 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001912 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001913 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001914
1915 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001916 if (!*args[1]) {
1917 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001918 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001919 goto out;
1920 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001921
William Lallemand6e62fb62015-04-28 16:55:23 +02001922 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1923 goto out;
1924
Emeric Brun32da3c42010-09-23 18:39:19 +02001925 err = invalid_char(args[1]);
1926 if (err) {
1927 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1928 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001929 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001930 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001931 }
1932
1933 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1934 /*
1935 * If there are two proxies with the same name only following
1936 * combinations are allowed:
1937 */
1938 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001939 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 +02001940 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001941 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001942 }
1943 }
1944
1945 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1946 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1947 err_code |= ERR_ALERT | ERR_ABORT;
1948 goto out;
1949 }
1950
1951 curpeers->next = peers;
1952 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001953 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001954 curpeers->conf.line = linenum;
1955 curpeers->last_change = now.tv_sec;
1956 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001957 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001958 }
1959 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001960 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001961 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001962 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001963
1964 if (!*args[2]) {
1965 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1966 file, linenum, args[0]);
1967 err_code |= ERR_ALERT | ERR_FATAL;
1968 goto out;
1969 }
1970
1971 err = invalid_char(args[1]);
1972 if (err) {
1973 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1974 file, linenum, *err, args[1]);
1975 err_code |= ERR_ALERT | ERR_FATAL;
1976 goto out;
1977 }
1978
1979 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1980 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1981 err_code |= ERR_ALERT | ERR_ABORT;
1982 goto out;
1983 }
1984
1985 /* the peers are linked backwards first */
1986 curpeers->count++;
1987 newpeer->next = curpeers->remote;
1988 curpeers->remote = newpeer;
1989 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001990 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001991 newpeer->conf.line = linenum;
1992
1993 newpeer->last_change = now.tv_sec;
1994 newpeer->id = strdup(args[1]);
1995
Willy Tarreau902636f2013-03-10 19:44:48 +01001996 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001997 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001998 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001999 err_code |= ERR_ALERT | ERR_FATAL;
2000 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002001 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002002
2003 proto = protocol_by_family(sk->ss_family);
2004 if (!proto || !proto->connect) {
2005 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2006 file, linenum, args[0], args[1]);
2007 err_code |= ERR_ALERT | ERR_FATAL;
2008 goto out;
2009 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002010
2011 if (port1 != port2) {
2012 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2013 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002014 err_code |= ERR_ALERT | ERR_FATAL;
2015 goto out;
2016 }
2017
Willy Tarreau2aa38802013-02-20 19:20:59 +01002018 if (!port1) {
2019 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2020 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002021 err_code |= ERR_ALERT | ERR_FATAL;
2022 goto out;
2023 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002024
Emeric Brun32da3c42010-09-23 18:39:19 +02002025 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002026 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002027 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002028 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002029
Emeric Brun32da3c42010-09-23 18:39:19 +02002030 if (strcmp(newpeer->id, localpeer) == 0) {
2031 /* Current is local peer, it define a frontend */
2032 newpeer->local = 1;
2033
2034 if (!curpeers->peers_fe) {
2035 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2036 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2037 err_code |= ERR_ALERT | ERR_ABORT;
2038 goto out;
2039 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002040
Willy Tarreau237250c2011-07-29 01:49:03 +02002041 init_new_proxy(curpeers->peers_fe);
2042 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002043 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002044 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2045 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002046 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002047
2048 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2049
Willy Tarreau902636f2013-03-10 19:44:48 +01002050 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2051 if (errmsg && *errmsg) {
2052 indent_msg(&errmsg, 2);
2053 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002054 }
2055 else
2056 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2057 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002058 err_code |= ERR_FATAL;
2059 goto out;
2060 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002061
2062 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002063 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002064 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2065 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002066 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002067 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002068 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002069 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002070 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2071 global.maxsock += l->maxconn;
2072 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002073 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002074 else {
2075 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2076 file, linenum, args[0], args[1],
2077 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2078 err_code |= ERR_FATAL;
2079 goto out;
2080 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002081 }
2082 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002083 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2084 curpeers->state = PR_STSTOPPED;
2085 }
2086 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2087 curpeers->state = PR_STNEW;
2088 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002089 else if (*args[0] != 0) {
2090 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2091 err_code |= ERR_ALERT | ERR_FATAL;
2092 goto out;
2093 }
2094
2095out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002096 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002097 return err_code;
2098}
2099
Simon Horman0d16a402015-01-30 11:22:58 +09002100
2101/*
William Lallemand51097192015-04-14 16:35:22 +02002102 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002103 * Returns the error code, 0 if OK, or any combination of :
2104 * - ERR_ABORT: must abort ASAP
2105 * - ERR_FATAL: we can continue parsing but not start the service
2106 * - ERR_WARN: a warning has been emitted
2107 * - ERR_ALERT: an alert has been emitted
2108 * Only the two first ones can stop processing, the two others are just
2109 * indicators.
2110 */
2111int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2112{
2113 static struct mailers *curmailers = NULL;
2114 struct mailer *newmailer = NULL;
2115 const char *err;
2116 int err_code = 0;
2117 char *errmsg = NULL;
2118
2119 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2120 if (!*args[1]) {
2121 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2122 err_code |= ERR_ALERT | ERR_ABORT;
2123 goto out;
2124 }
2125
2126 err = invalid_char(args[1]);
2127 if (err) {
2128 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2129 file, linenum, *err, args[0], args[1]);
2130 err_code |= ERR_ALERT | ERR_ABORT;
2131 goto out;
2132 }
2133
2134 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2135 /*
2136 * If there are two proxies with the same name only following
2137 * combinations are allowed:
2138 */
2139 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002140 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 +09002141 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002142 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002143 }
2144 }
2145
2146 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2147 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2148 err_code |= ERR_ALERT | ERR_ABORT;
2149 goto out;
2150 }
2151
2152 curmailers->next = mailers;
2153 mailers = curmailers;
2154 curmailers->conf.file = strdup(file);
2155 curmailers->conf.line = linenum;
2156 curmailers->id = strdup(args[1]);
2157 }
2158 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2159 struct sockaddr_storage *sk;
2160 int port1, port2;
2161 struct protocol *proto;
2162
2163 if (!*args[2]) {
2164 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2165 file, linenum, args[0]);
2166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
2168 }
2169
2170 err = invalid_char(args[1]);
2171 if (err) {
2172 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2173 file, linenum, *err, args[1]);
2174 err_code |= ERR_ALERT | ERR_FATAL;
2175 goto out;
2176 }
2177
2178 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2179 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2180 err_code |= ERR_ALERT | ERR_ABORT;
2181 goto out;
2182 }
2183
2184 /* the mailers are linked backwards first */
2185 curmailers->count++;
2186 newmailer->next = curmailers->mailer_list;
2187 curmailers->mailer_list = newmailer;
2188 newmailer->mailers = curmailers;
2189 newmailer->conf.file = strdup(file);
2190 newmailer->conf.line = linenum;
2191
2192 newmailer->id = strdup(args[1]);
2193
2194 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2195 if (!sk) {
2196 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
2199 }
2200
2201 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002202 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2203 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002204 file, linenum, args[0], args[1]);
2205 err_code |= ERR_ALERT | ERR_FATAL;
2206 goto out;
2207 }
2208
2209 if (port1 != port2) {
2210 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2211 file, linenum, args[0], args[1], args[2]);
2212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
2214 }
2215
2216 if (!port1) {
2217 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2218 file, linenum, args[0], args[1], args[2]);
2219 err_code |= ERR_ALERT | ERR_FATAL;
2220 goto out;
2221 }
2222
2223 newmailer->addr = *sk;
2224 newmailer->proto = proto;
2225 newmailer->xprt = &raw_sock;
2226 newmailer->sock_init_arg = NULL;
2227 } /* neither "mailer" nor "mailers" */
2228 else if (*args[0] != 0) {
2229 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2230 err_code |= ERR_ALERT | ERR_FATAL;
2231 goto out;
2232 }
2233
2234out:
2235 free(errmsg);
2236 return err_code;
2237}
2238
Simon Horman9dc49962015-01-30 11:22:59 +09002239static void free_email_alert(struct proxy *p)
2240{
2241 free(p->email_alert.mailers.name);
2242 p->email_alert.mailers.name = NULL;
2243 free(p->email_alert.from);
2244 p->email_alert.from = NULL;
2245 free(p->email_alert.to);
2246 p->email_alert.to = NULL;
2247 free(p->email_alert.myhostname);
2248 p->email_alert.myhostname = NULL;
2249}
2250
Willy Tarreau3842f002009-06-14 11:39:52 +02002251int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002252{
2253 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002254 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002255 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002256 int rc;
2257 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002258 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002259 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002260 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002261 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002262 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002263
Willy Tarreau977b8e42006-12-29 14:19:17 +01002264 if (!strcmp(args[0], "listen"))
2265 rc = PR_CAP_LISTEN;
2266 else if (!strcmp(args[0], "frontend"))
2267 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002268 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002269 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002270 else
2271 rc = PR_CAP_NONE;
2272
2273 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002274 if (!*args[1]) {
2275 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2276 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2277 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002278 err_code |= ERR_ALERT | ERR_ABORT;
2279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002280 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002281
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002282 err = invalid_char(args[1]);
2283 if (err) {
2284 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2285 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002286 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002287 }
2288
Willy Tarreau8f50b682015-05-26 11:45:02 +02002289 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2290 if (curproxy) {
2291 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2292 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2293 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002294 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002295 }
2296
Willy Tarreaubaaee002006-06-26 02:48:02 +02002297 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2298 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002299 err_code |= ERR_ALERT | ERR_ABORT;
2300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002301 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002302
Willy Tarreau97cb7802010-01-03 20:23:58 +01002303 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002304 curproxy->next = proxy;
2305 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002306 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2307 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002308 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002310 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002311 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002312
William Lallemand6e62fb62015-04-28 16:55:23 +02002313 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2314 if (curproxy->cap & PR_CAP_FE)
2315 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2316 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002317 }
2318
2319 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002320 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002321 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002322
Willy Tarreaubaaee002006-06-26 02:48:02 +02002323 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002324 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002325 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002326 curproxy->no_options = defproxy.no_options;
2327 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002328 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002329 curproxy->except_net = defproxy.except_net;
2330 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002331 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002332 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002333
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002334 if (defproxy.fwdfor_hdr_len) {
2335 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2336 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2337 }
2338
Willy Tarreaub86db342009-11-30 11:50:16 +01002339 if (defproxy.orgto_hdr_len) {
2340 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2341 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2342 }
2343
Mark Lamourinec2247f02012-01-04 13:02:01 -05002344 if (defproxy.server_id_hdr_len) {
2345 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2346 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2347 }
2348
Willy Tarreau977b8e42006-12-29 14:19:17 +01002349 if (curproxy->cap & PR_CAP_FE) {
2350 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002351 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002352 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002353
2354 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002355 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2356 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002357
2358 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2359 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360
Willy Tarreau977b8e42006-12-29 14:19:17 +01002361 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002362 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002363 curproxy->fullconn = defproxy.fullconn;
2364 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002365 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002366 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002367
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002368 if (defproxy.check_req) {
2369 curproxy->check_req = calloc(1, defproxy.check_len);
2370 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2371 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002372 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002374 if (defproxy.expect_str) {
2375 curproxy->expect_str = strdup(defproxy.expect_str);
2376 if (defproxy.expect_regex) {
2377 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002378 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2379 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002380 }
2381 }
2382
Willy Tarreau67402132012-05-31 20:40:20 +02002383 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002384 if (defproxy.cookie_name)
2385 curproxy->cookie_name = strdup(defproxy.cookie_name);
2386 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002387 if (defproxy.cookie_domain)
2388 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002389
Willy Tarreau31936852010-10-06 16:59:56 +02002390 if (defproxy.cookie_maxidle)
2391 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2392
2393 if (defproxy.cookie_maxlife)
2394 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2395
Emeric Brun647caf12009-06-30 17:57:00 +02002396 if (defproxy.rdp_cookie_name)
2397 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2398 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2399
Willy Tarreau01732802007-11-01 22:48:15 +01002400 if (defproxy.url_param_name)
2401 curproxy->url_param_name = strdup(defproxy.url_param_name);
2402 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002403
Benoitaffb4812009-03-25 13:02:10 +01002404 if (defproxy.hh_name)
2405 curproxy->hh_name = strdup(defproxy.hh_name);
2406 curproxy->hh_len = defproxy.hh_len;
2407 curproxy->hh_match_domain = defproxy.hh_match_domain;
2408
Willy Tarreauef9a3602012-12-08 22:29:20 +01002409 if (defproxy.conn_src.iface_name)
2410 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2411 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002412 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002413#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002414 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002415#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002416 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002418 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002419 if (defproxy.capture_name)
2420 curproxy->capture_name = strdup(defproxy.capture_name);
2421 curproxy->capture_namelen = defproxy.capture_namelen;
2422 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002423 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424
Willy Tarreau977b8e42006-12-29 14:19:17 +01002425 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002426 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002427 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002428 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002429 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002430 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002431 curproxy->mon_net = defproxy.mon_net;
2432 curproxy->mon_mask = defproxy.mon_mask;
2433 if (defproxy.monitor_uri)
2434 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2435 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002436 if (defproxy.defbe.name)
2437 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002438
2439 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002440 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2441 if (curproxy->conf.logformat_string &&
2442 curproxy->conf.logformat_string != default_http_log_format &&
2443 curproxy->conf.logformat_string != default_tcp_log_format &&
2444 curproxy->conf.logformat_string != clf_http_log_format)
2445 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2446
2447 if (defproxy.conf.lfs_file) {
2448 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2449 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2450 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002451 }
2452
2453 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002454 curproxy->timeout.connect = defproxy.timeout.connect;
2455 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002456 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002457 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002458 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002459 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002460 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002461 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002462 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002463 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002464 }
2465
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002467 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002468
2469 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002470 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002471 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002472 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002473 LIST_INIT(&node->list);
2474 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2475 }
2476
Willy Tarreau62a61232013-04-12 18:13:46 +02002477 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2478 if (curproxy->conf.uniqueid_format_string)
2479 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2480
Willy Tarreau094af4e2015-01-07 15:03:42 +01002481 if (defproxy.log_tag)
2482 curproxy->log_tag = strdup(defproxy.log_tag);
2483
Willy Tarreau62a61232013-04-12 18:13:46 +02002484 if (defproxy.conf.uif_file) {
2485 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2486 curproxy->conf.uif_line = defproxy.conf.uif_line;
2487 }
William Lallemanda73203e2012-03-12 12:48:57 +01002488
2489 /* copy default header unique id */
2490 if (defproxy.header_unique_id)
2491 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2492
William Lallemand82fe75c2012-10-23 10:25:10 +02002493 /* default compression options */
2494 if (defproxy.comp != NULL) {
2495 curproxy->comp = calloc(1, sizeof(struct comp));
2496 curproxy->comp->algos = defproxy.comp->algos;
2497 curproxy->comp->types = defproxy.comp->types;
2498 }
2499
Willy Tarreaubaaee002006-06-26 02:48:02 +02002500 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002501 curproxy->conf.used_listener_id = EB_ROOT;
2502 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002503
Simon Horman98637e52014-06-20 12:30:16 +09002504 if (defproxy.check_path)
2505 curproxy->check_path = strdup(defproxy.check_path);
2506 if (defproxy.check_command)
2507 curproxy->check_command = strdup(defproxy.check_command);
2508
Simon Horman9dc49962015-01-30 11:22:59 +09002509 if (defproxy.email_alert.mailers.name)
2510 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2511 if (defproxy.email_alert.from)
2512 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2513 if (defproxy.email_alert.to)
2514 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2515 if (defproxy.email_alert.myhostname)
2516 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002517 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002518
Willy Tarreau93893792009-07-23 13:19:11 +02002519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002520 }
2521 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2522 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002523 /* FIXME-20070101: we should do this too at the end of the
2524 * config parsing to free all default values.
2525 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002526 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2527 err_code |= ERR_ABORT;
2528 goto out;
2529 }
2530
Willy Tarreaua534fea2008-08-03 12:19:50 +02002531 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002532 free(defproxy.check_command);
2533 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002534 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002535 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002536 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002537 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002538 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002539 free(defproxy.capture_name);
2540 free(defproxy.monitor_uri);
2541 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002542 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002543 free(defproxy.fwdfor_hdr_name);
2544 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002545 free(defproxy.orgto_hdr_name);
2546 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002547 free(defproxy.server_id_hdr_name);
2548 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002549 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002550 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002551 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002552 free(defproxy.expect_regex);
2553 defproxy.expect_regex = NULL;
2554 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002555
Willy Tarreau62a61232013-04-12 18:13:46 +02002556 if (defproxy.conf.logformat_string != default_http_log_format &&
2557 defproxy.conf.logformat_string != default_tcp_log_format &&
2558 defproxy.conf.logformat_string != clf_http_log_format)
2559 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002560
Willy Tarreau62a61232013-04-12 18:13:46 +02002561 free(defproxy.conf.uniqueid_format_string);
2562 free(defproxy.conf.lfs_file);
2563 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002564 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002565 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002566
Willy Tarreaua534fea2008-08-03 12:19:50 +02002567 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002568 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002569
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 /* we cannot free uri_auth because it might already be used */
2571 init_default_instance();
2572 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002573 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2574 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002575 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 }
2578 else if (curproxy == NULL) {
2579 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002580 err_code |= ERR_ALERT | ERR_FATAL;
2581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002583
2584 /* update the current file and line being parsed */
2585 curproxy->conf.args.file = curproxy->conf.file;
2586 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002587
2588 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002589 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2590 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2591 if (err_code & ERR_FATAL)
2592 goto out;
2593 }
2594 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002595 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002596 int cur_arg;
2597
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598 if (curproxy == &defproxy) {
2599 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002600 err_code |= ERR_ALERT | ERR_FATAL;
2601 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002603 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002604 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605
Willy Tarreau24709282013-03-10 21:32:12 +01002606 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002607 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002608 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002609 err_code |= ERR_ALERT | ERR_FATAL;
2610 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002612
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002613 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002614
2615 /* use default settings for unix sockets */
2616 bind_conf->ux.uid = global.unix_bind.ux.uid;
2617 bind_conf->ux.gid = global.unix_bind.ux.gid;
2618 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002619
2620 /* NOTE: the following line might create several listeners if there
2621 * are comma-separated IPs or port ranges. So all further processing
2622 * will have to be applied to all listeners created after last_listen.
2623 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002624 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2625 if (errmsg && *errmsg) {
2626 indent_msg(&errmsg, 2);
2627 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002628 }
2629 else
2630 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2631 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002632 err_code |= ERR_ALERT | ERR_FATAL;
2633 goto out;
2634 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002635
Willy Tarreau4348fad2012-09-20 16:48:07 +02002636 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2637 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002638 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002639 }
2640
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002641 cur_arg = 2;
2642 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002643 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002644 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002645 char *err;
2646
Willy Tarreau26982662012-09-12 23:17:10 +02002647 kw = bind_find_kw(args[cur_arg]);
2648 if (kw) {
2649 char *err = NULL;
2650 int code;
2651
2652 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002653 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2654 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002655 cur_arg += 1 + kw->skip ;
2656 err_code |= ERR_ALERT | ERR_FATAL;
2657 goto out;
2658 }
2659
Willy Tarreau4348fad2012-09-20 16:48:07 +02002660 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002661 err_code |= code;
2662
2663 if (code) {
2664 if (err && *err) {
2665 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002666 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002667 }
2668 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002669 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2670 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002671 if (code & ERR_FATAL) {
2672 free(err);
2673 cur_arg += 1 + kw->skip;
2674 goto out;
2675 }
2676 }
2677 free(err);
2678 cur_arg += 1 + kw->skip;
2679 continue;
2680 }
2681
Willy Tarreau8638f482012-09-18 18:01:17 +02002682 err = NULL;
2683 if (!bind_dumped) {
2684 bind_dump_kws(&err);
2685 indent_msg(&err, 4);
2686 bind_dumped = 1;
2687 }
2688
2689 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2690 file, linenum, args[0], args[1], args[cur_arg],
2691 err ? " Registered keywords :" : "", err ? err : "");
2692 free(err);
2693
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002696 }
Willy Tarreau93893792009-07-23 13:19:11 +02002697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002698 }
2699 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002700 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002701 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2702 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002706 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002707 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002708
Willy Tarreaubaaee002006-06-26 02:48:02 +02002709 /* flush useless bits */
2710 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002711 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002712 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002713 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002714 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002715 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002716
William Lallemanddf1425a2015-04-28 20:17:49 +02002717 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2718 goto out;
2719
Willy Tarreau1c47f852006-07-09 08:22:27 +02002720 if (!*args[1]) {
2721 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2722 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002723 err_code |= ERR_ALERT | ERR_FATAL;
2724 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002725 }
2726
Willy Tarreaua534fea2008-08-03 12:19:50 +02002727 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002728 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002729 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002730 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002731 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2732
Willy Tarreau93893792009-07-23 13:19:11 +02002733 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002734 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002735 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02002736 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2737 goto out;
2738
Willy Tarreaubaaee002006-06-26 02:48:02 +02002739 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2740 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2741 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2742 else {
2743 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002744 err_code |= ERR_ALERT | ERR_FATAL;
2745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002746 }
2747 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002748 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002749 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002750
2751 if (curproxy == &defproxy) {
2752 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2753 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002756 }
2757
William Lallemanddf1425a2015-04-28 20:17:49 +02002758 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2759 goto out;
2760
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002761 if (!*args[1]) {
2762 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2763 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002764 err_code |= ERR_ALERT | ERR_FATAL;
2765 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002766 }
2767
2768 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002769 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02002770 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002771
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002772 if (curproxy->uuid <= 0) {
2773 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002774 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002775 err_code |= ERR_ALERT | ERR_FATAL;
2776 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002777 }
2778
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002779 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2780 if (node) {
2781 struct proxy *target = container_of(node, struct proxy, conf.id);
2782 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2783 file, linenum, proxy_type_str(curproxy), curproxy->id,
2784 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2785 err_code |= ERR_ALERT | ERR_FATAL;
2786 goto out;
2787 }
2788 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002789 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002790 else if (!strcmp(args[0], "description")) {
2791 int i, len=0;
2792 char *d;
2793
Cyril Bonté99ed3272010-01-24 23:29:44 +01002794 if (curproxy == &defproxy) {
2795 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2796 file, linenum, args[0]);
2797 err_code |= ERR_ALERT | ERR_FATAL;
2798 goto out;
2799 }
2800
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002801 if (!*args[1]) {
2802 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2803 file, linenum, args[0]);
2804 return -1;
2805 }
2806
Willy Tarreau348acfe2014-04-14 15:00:39 +02002807 for (i = 1; *args[i]; i++)
2808 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002809
2810 d = (char *)calloc(1, len);
2811 curproxy->desc = d;
2812
Willy Tarreau348acfe2014-04-14 15:00:39 +02002813 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2814 for (i = 2; *args[i]; i++)
2815 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002816
2817 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002818 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02002819 if (alertif_too_many_args(0, file, linenum, args, &err_code))
2820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002821 curproxy->state = PR_STSTOPPED;
2822 }
2823 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02002824 if (alertif_too_many_args(0, file, linenum, args, &err_code))
2825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002826 curproxy->state = PR_STNEW;
2827 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002828 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2829 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002830 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002831
2832 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002833 unsigned int low, high;
2834
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002835 if (strcmp(args[cur_arg], "all") == 0) {
2836 set = 0;
2837 break;
2838 }
2839 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002840 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002841 }
2842 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002843 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002844 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002845 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002846 char *dash = strchr(args[cur_arg], '-');
2847
2848 low = high = str2uic(args[cur_arg]);
2849 if (dash)
2850 high = str2uic(dash + 1);
2851
2852 if (high < low) {
2853 unsigned int swap = low;
2854 low = high;
2855 high = swap;
2856 }
2857
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002858 if (low < 1 || high > LONGBITS) {
2859 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2860 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002863 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002864 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002865 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002866 }
2867 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002868 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2869 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002870 err_code |= ERR_ALERT | ERR_FATAL;
2871 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002872 }
2873 cur_arg++;
2874 }
2875 curproxy->bind_proc = set;
2876 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002877 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002878 if (curproxy == &defproxy) {
2879 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002880 err_code |= ERR_ALERT | ERR_FATAL;
2881 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002882 }
2883
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002884 err = invalid_char(args[1]);
2885 if (err) {
2886 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2887 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002888 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002889 }
2890
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002891 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002892 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2893 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002896 }
2897 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002898 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2899 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002900
Willy Tarreau977b8e42006-12-29 14:19:17 +01002901 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002902 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002903
Willy Tarreaubaaee002006-06-26 02:48:02 +02002904 if (*(args[1]) == 0) {
2905 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2906 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002907 err_code |= ERR_ALERT | ERR_FATAL;
2908 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002909 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002910
Willy Tarreau67402132012-05-31 20:40:20 +02002911 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002912 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002913 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002914 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 curproxy->cookie_name = strdup(args[1]);
2916 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002917
Willy Tarreaubaaee002006-06-26 02:48:02 +02002918 cur_arg = 2;
2919 while (*(args[cur_arg])) {
2920 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002921 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002922 }
2923 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002924 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002925 }
2926 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002927 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002928 }
2929 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002930 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002931 }
2932 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002933 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002934 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002935 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002936 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002937 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002938 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002939 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002940 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002941 else if (!strcmp(args[cur_arg], "httponly")) {
2942 curproxy->ck_opts |= PR_CK_HTTPONLY;
2943 }
2944 else if (!strcmp(args[cur_arg], "secure")) {
2945 curproxy->ck_opts |= PR_CK_SECURE;
2946 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002947 else if (!strcmp(args[cur_arg], "domain")) {
2948 if (!*args[cur_arg + 1]) {
2949 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2950 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002951 err_code |= ERR_ALERT | ERR_FATAL;
2952 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002953 }
2954
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002955 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002956 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002957 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2958 " dots nor does not start with a dot."
2959 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002960 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002961 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002962 }
2963
2964 err = invalid_domainchar(args[cur_arg + 1]);
2965 if (err) {
2966 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2967 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002970 }
2971
Willy Tarreau68a897b2009-12-03 23:28:34 +01002972 if (!curproxy->cookie_domain) {
2973 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2974 } else {
2975 /* one domain was already specified, add another one by
2976 * building the string which will be returned along with
2977 * the cookie.
2978 */
2979 char *new_ptr;
2980 int new_len = strlen(curproxy->cookie_domain) +
2981 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2982 new_ptr = malloc(new_len);
2983 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2984 free(curproxy->cookie_domain);
2985 curproxy->cookie_domain = new_ptr;
2986 }
Willy Tarreau31936852010-10-06 16:59:56 +02002987 cur_arg++;
2988 }
2989 else if (!strcmp(args[cur_arg], "maxidle")) {
2990 unsigned int maxidle;
2991 const char *res;
2992
2993 if (!*args[cur_arg + 1]) {
2994 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2995 file, linenum, args[cur_arg]);
2996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
2998 }
2999
3000 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3001 if (res) {
3002 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3003 file, linenum, *res, args[cur_arg]);
3004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
3006 }
3007 curproxy->cookie_maxidle = maxidle;
3008 cur_arg++;
3009 }
3010 else if (!strcmp(args[cur_arg], "maxlife")) {
3011 unsigned int maxlife;
3012 const char *res;
3013
3014 if (!*args[cur_arg + 1]) {
3015 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3016 file, linenum, args[cur_arg]);
3017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
3019 }
3020
3021 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3022 if (res) {
3023 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3024 file, linenum, *res, args[cur_arg]);
3025 err_code |= ERR_ALERT | ERR_FATAL;
3026 goto out;
3027 }
3028 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003029 cur_arg++;
3030 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003031 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003032 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 +02003033 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003034 err_code |= ERR_ALERT | ERR_FATAL;
3035 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003036 }
3037 cur_arg++;
3038 }
Willy Tarreau67402132012-05-31 20:40:20 +02003039 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3041 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003042 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003043 }
3044
Willy Tarreau67402132012-05-31 20:40:20 +02003045 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3047 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003049 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003050
Willy Tarreau67402132012-05-31 20:40:20 +02003051 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003052 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3053 file, linenum);
3054 err_code |= ERR_ALERT | ERR_FATAL;
3055 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003056 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003057 else if (!strcmp(args[0], "email-alert")) {
3058 if (*(args[1]) == 0) {
3059 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3060 file, linenum, args[0]);
3061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
3063 }
3064
3065 if (!strcmp(args[1], "from")) {
3066 if (*(args[1]) == 0) {
3067 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3068 file, linenum, args[1]);
3069 err_code |= ERR_ALERT | ERR_FATAL;
3070 goto out;
3071 }
3072 free(curproxy->email_alert.from);
3073 curproxy->email_alert.from = strdup(args[2]);
3074 }
3075 else if (!strcmp(args[1], "mailers")) {
3076 if (*(args[1]) == 0) {
3077 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3078 file, linenum, args[1]);
3079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
3081 }
3082 free(curproxy->email_alert.mailers.name);
3083 curproxy->email_alert.mailers.name = strdup(args[2]);
3084 }
3085 else if (!strcmp(args[1], "myhostname")) {
3086 if (*(args[1]) == 0) {
3087 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3088 file, linenum, args[1]);
3089 err_code |= ERR_ALERT | ERR_FATAL;
3090 goto out;
3091 }
3092 free(curproxy->email_alert.myhostname);
3093 curproxy->email_alert.myhostname = strdup(args[2]);
3094 }
Simon Horman64e34162015-02-06 11:11:57 +09003095 else if (!strcmp(args[1], "level")) {
3096 curproxy->email_alert.level = get_log_level(args[2]);
3097 if (curproxy->email_alert.level < 0) {
3098 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3099 file, linenum, args[1], args[2]);
3100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
3102 }
3103 }
Simon Horman9dc49962015-01-30 11:22:59 +09003104 else if (!strcmp(args[1], "to")) {
3105 if (*(args[1]) == 0) {
3106 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3107 file, linenum, args[1]);
3108 err_code |= ERR_ALERT | ERR_FATAL;
3109 goto out;
3110 }
3111 free(curproxy->email_alert.to);
3112 curproxy->email_alert.to = strdup(args[2]);
3113 }
3114 else {
3115 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3116 file, linenum, args[1]);
3117 err_code |= ERR_ALERT | ERR_FATAL;
3118 goto out;
3119 }
Simon Horman64e34162015-02-06 11:11:57 +09003120 /* Indicate that the email_alert is at least partially configured */
3121 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003122 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003123 else if (!strcmp(args[0], "external-check")) {
3124 if (*(args[1]) == 0) {
3125 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3126 file, linenum, args[0]);
3127 err_code |= ERR_ALERT | ERR_FATAL;
3128 goto out;
3129 }
3130
3131 if (!strcmp(args[1], "command")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003132 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3133 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003134 if (*(args[1]) == 0) {
3135 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3136 file, linenum, args[1]);
3137 err_code |= ERR_ALERT | ERR_FATAL;
3138 goto out;
3139 }
3140 free(curproxy->check_command);
3141 curproxy->check_command = strdup(args[2]);
3142 }
3143 else if (!strcmp(args[1], "path")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003144 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3145 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003146 if (*(args[1]) == 0) {
3147 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3148 file, linenum, args[1]);
3149 err_code |= ERR_ALERT | ERR_FATAL;
3150 goto out;
3151 }
3152 free(curproxy->check_path);
3153 curproxy->check_path = strdup(args[2]);
3154 }
3155 else {
3156 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3157 file, linenum, args[1]);
3158 err_code |= ERR_ALERT | ERR_FATAL;
3159 goto out;
3160 }
3161 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003162 else if (!strcmp(args[0], "persist")) { /* persist */
3163 if (*(args[1]) == 0) {
3164 Alert("parsing [%s:%d] : missing persist method.\n",
3165 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003166 err_code |= ERR_ALERT | ERR_FATAL;
3167 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003168 }
3169
3170 if (!strncmp(args[1], "rdp-cookie", 10)) {
3171 curproxy->options2 |= PR_O2_RDPC_PRST;
3172
Emeric Brunb982a3d2010-01-04 15:45:53 +01003173 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003174 const char *beg, *end;
3175
3176 beg = args[1] + 11;
3177 end = strchr(beg, ')');
3178
William Lallemanddf1425a2015-04-28 20:17:49 +02003179 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3180 goto out;
3181
Emeric Brun647caf12009-06-30 17:57:00 +02003182 if (!end || end == beg) {
3183 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3184 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003185 err_code |= ERR_ALERT | ERR_FATAL;
3186 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003187 }
3188
3189 free(curproxy->rdp_cookie_name);
3190 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3191 curproxy->rdp_cookie_len = end-beg;
3192 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003193 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003194 free(curproxy->rdp_cookie_name);
3195 curproxy->rdp_cookie_name = strdup("msts");
3196 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3197 }
3198 else { /* syntax */
3199 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3200 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003201 err_code |= ERR_ALERT | ERR_FATAL;
3202 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003203 }
3204 }
3205 else {
3206 Alert("parsing [%s:%d] : unknown persist method.\n",
3207 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003208 err_code |= ERR_ALERT | ERR_FATAL;
3209 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003210 }
3211 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003212 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003213 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003214
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003215 if (curproxy == &defproxy) {
3216 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3217 err_code |= ERR_ALERT | ERR_FATAL;
3218 goto out;
3219 }
3220
Willy Tarreau977b8e42006-12-29 14:19:17 +01003221 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003222 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003223
Willy Tarreaubaaee002006-06-26 02:48:02 +02003224 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003225 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003226 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003227 err_code |= ERR_ALERT | ERR_FATAL;
3228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229 }
3230 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003231 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 curproxy->appsession_name = strdup(args[1]);
3233 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3234 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003235 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3236 if (err) {
3237 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3238 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003239 err_code |= ERR_ALERT | ERR_FATAL;
3240 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003241 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003242 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003243
Willy Tarreau51041c72007-09-09 21:56:53 +02003244 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3245 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003246 err_code |= ERR_ALERT | ERR_ABORT;
3247 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003248 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003249
3250 cur_arg = 6;
3251 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003252 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3253 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003254 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003255 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003256 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003257 } else if (!strcmp(args[cur_arg], "prefix")) {
3258 curproxy->options2 |= PR_O2_AS_PFX;
3259 } else if (!strcmp(args[cur_arg], "mode")) {
3260 if (!*args[cur_arg + 1]) {
3261 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3262 file, linenum, args[0], args[cur_arg]);
3263 err_code |= ERR_ALERT | ERR_FATAL;
3264 goto out;
3265 }
3266
3267 cur_arg++;
3268 if (!strcmp(args[cur_arg], "query-string")) {
3269 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3270 curproxy->options2 |= PR_O2_AS_M_QS;
3271 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3272 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3273 curproxy->options2 |= PR_O2_AS_M_PP;
3274 } else {
3275 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3276 err_code |= ERR_ALERT | ERR_FATAL;
3277 goto out;
3278 }
3279 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003280 cur_arg++;
3281 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 } /* Url App Session */
3283 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003284 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003285 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003286
Willy Tarreaubaaee002006-06-26 02:48:02 +02003287 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003288 if (curproxy == &defproxy) {
3289 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
3292 }
3293
William Lallemand1a748ae2015-05-19 16:37:23 +02003294 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3295 goto out;
3296
Willy Tarreaubaaee002006-06-26 02:48:02 +02003297 if (*(args[4]) == 0) {
3298 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3299 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003300 err_code |= ERR_ALERT | ERR_FATAL;
3301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003303 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 curproxy->capture_name = strdup(args[2]);
3305 curproxy->capture_namelen = strlen(curproxy->capture_name);
3306 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003307 curproxy->to_log |= LW_COOKIE;
3308 }
3309 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3310 struct cap_hdr *hdr;
3311
3312 if (curproxy == &defproxy) {
3313 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 +02003314 err_code |= ERR_ALERT | ERR_FATAL;
3315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003316 }
3317
William Lallemand1a748ae2015-05-19 16:37:23 +02003318 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3319 goto out;
3320
Willy Tarreaubaaee002006-06-26 02:48:02 +02003321 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3322 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3323 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003324 err_code |= ERR_ALERT | ERR_FATAL;
3325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003326 }
3327
3328 hdr = calloc(sizeof(struct cap_hdr), 1);
3329 hdr->next = curproxy->req_cap;
3330 hdr->name = strdup(args[3]);
3331 hdr->namelen = strlen(args[3]);
3332 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003333 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003334 hdr->index = curproxy->nb_req_cap++;
3335 curproxy->req_cap = hdr;
3336 curproxy->to_log |= LW_REQHDR;
3337 }
3338 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3339 struct cap_hdr *hdr;
3340
3341 if (curproxy == &defproxy) {
3342 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 +02003343 err_code |= ERR_ALERT | ERR_FATAL;
3344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003345 }
3346
William Lallemand1a748ae2015-05-19 16:37:23 +02003347 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3348 goto out;
3349
Willy Tarreaubaaee002006-06-26 02:48:02 +02003350 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3351 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3352 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003355 }
3356 hdr = calloc(sizeof(struct cap_hdr), 1);
3357 hdr->next = curproxy->rsp_cap;
3358 hdr->name = strdup(args[3]);
3359 hdr->namelen = strlen(args[3]);
3360 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003361 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003362 hdr->index = curproxy->nb_rsp_cap++;
3363 curproxy->rsp_cap = hdr;
3364 curproxy->to_log |= LW_RSPHDR;
3365 }
3366 else {
3367 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3368 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003369 err_code |= ERR_ALERT | ERR_FATAL;
3370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003371 }
3372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003374 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003375 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003376
William Lallemanddf1425a2015-04-28 20:17:49 +02003377 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3378 goto out;
3379
Willy Tarreaubaaee002006-06-26 02:48:02 +02003380 if (*(args[1]) == 0) {
3381 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3382 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003383 err_code |= ERR_ALERT | ERR_FATAL;
3384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 }
3386 curproxy->conn_retries = atol(args[1]);
3387 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003388 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003389 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003390
3391 if (curproxy == &defproxy) {
3392 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3393 err_code |= ERR_ALERT | ERR_FATAL;
3394 goto out;
3395 }
3396
Willy Tarreau20b0de52012-12-24 15:45:22 +01003397 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3398 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3399 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3400 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003401 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003402 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3403 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 +01003404 file, linenum, args[0]);
3405 err_code |= ERR_WARN;
3406 }
3407
Willy Tarreauff011f22011-01-06 17:51:27 +01003408 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003409
Willy Tarreauff011f22011-01-06 17:51:27 +01003410 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003411 err_code |= ERR_ALERT | ERR_ABORT;
3412 goto out;
3413 }
3414
Willy Tarreau5002f572014-04-23 01:32:02 +02003415 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003416 err_code |= warnif_cond_conflicts(rule->cond,
3417 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3418 file, linenum);
3419
Willy Tarreauff011f22011-01-06 17:51:27 +01003420 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003421 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003422 else if (!strcmp(args[0], "http-response")) { /* response access control */
3423 struct http_res_rule *rule;
3424
3425 if (curproxy == &defproxy) {
3426 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3427 err_code |= ERR_ALERT | ERR_FATAL;
3428 goto out;
3429 }
3430
3431 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3432 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3433 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3434 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3435 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3436 file, linenum, args[0]);
3437 err_code |= ERR_WARN;
3438 }
3439
3440 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3441
3442 if (!rule) {
3443 err_code |= ERR_ALERT | ERR_ABORT;
3444 goto out;
3445 }
3446
3447 err_code |= warnif_cond_conflicts(rule->cond,
3448 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3449 file, linenum);
3450
3451 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3452 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003453 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3454 /* set the header name and length into the proxy structure */
3455 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3456 err_code |= ERR_WARN;
3457
3458 if (!*args[1]) {
3459 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3460 file, linenum, args[0]);
3461 err_code |= ERR_ALERT | ERR_FATAL;
3462 goto out;
3463 }
3464
3465 /* set the desired header name */
3466 free(curproxy->server_id_hdr_name);
3467 curproxy->server_id_hdr_name = strdup(args[1]);
3468 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3469 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003470 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003471 struct http_req_rule *rule;
3472
Willy Tarreaub099aca2008-10-12 17:26:37 +02003473 if (curproxy == &defproxy) {
3474 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003477 }
3478
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003479 /* emulate "block" using "http-request block". Since these rules are supposed to
3480 * be processed before all http-request rules, we put them into their own list
3481 * and will insert them at the end.
3482 */
3483 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3484 if (!rule) {
3485 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003486 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003487 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003488 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3489 err_code |= warnif_cond_conflicts(rule->cond,
3490 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3491 file, linenum);
3492 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003493
3494 if (!already_warned(WARN_BLOCK_DEPRECATED))
3495 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]);
3496
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003497 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003498 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003499 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003500
Cyril Bonté99ed3272010-01-24 23:29:44 +01003501 if (curproxy == &defproxy) {
3502 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3503 err_code |= ERR_ALERT | ERR_FATAL;
3504 goto out;
3505 }
3506
Willy Tarreaube4653b2015-05-28 15:26:58 +02003507 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003508 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3509 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003510 err_code |= ERR_ALERT | ERR_FATAL;
3511 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003512 }
3513
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003514 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003515 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003516 err_code |= warnif_cond_conflicts(rule->cond,
3517 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3518 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003519 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003520 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003521 struct switching_rule *rule;
3522
Willy Tarreaub099aca2008-10-12 17:26:37 +02003523 if (curproxy == &defproxy) {
3524 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003525 err_code |= ERR_ALERT | ERR_FATAL;
3526 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003527 }
3528
Willy Tarreau55ea7572007-06-17 19:56:27 +02003529 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003530 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003531
3532 if (*(args[1]) == 0) {
3533 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003536 }
3537
Willy Tarreauf51658d2014-04-23 01:21:56 +02003538 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3539 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3540 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3541 file, linenum, errmsg);
3542 err_code |= ERR_ALERT | ERR_FATAL;
3543 goto out;
3544 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003545
Willy Tarreauf51658d2014-04-23 01:21:56 +02003546 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003547 }
3548
3549 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3550 rule->cond = cond;
3551 rule->be.name = strdup(args[1]);
3552 LIST_INIT(&rule->list);
3553 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3554 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003555 else if (strcmp(args[0], "use-server") == 0) {
3556 struct server_rule *rule;
3557
3558 if (curproxy == &defproxy) {
3559 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3560 err_code |= ERR_ALERT | ERR_FATAL;
3561 goto out;
3562 }
3563
3564 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3565 err_code |= ERR_WARN;
3566
3567 if (*(args[1]) == 0) {
3568 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3569 err_code |= ERR_ALERT | ERR_FATAL;
3570 goto out;
3571 }
3572
3573 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3574 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3575 file, linenum, args[0]);
3576 err_code |= ERR_ALERT | ERR_FATAL;
3577 goto out;
3578 }
3579
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003580 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3581 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3582 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003583 err_code |= ERR_ALERT | ERR_FATAL;
3584 goto out;
3585 }
3586
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003587 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003588
3589 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3590 rule->cond = cond;
3591 rule->srv.name = strdup(args[1]);
3592 LIST_INIT(&rule->list);
3593 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3594 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3595 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003596 else if ((!strcmp(args[0], "force-persist")) ||
3597 (!strcmp(args[0], "ignore-persist"))) {
3598 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003599
3600 if (curproxy == &defproxy) {
3601 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3602 err_code |= ERR_ALERT | ERR_FATAL;
3603 goto out;
3604 }
3605
3606 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3607 err_code |= ERR_WARN;
3608
Willy Tarreauef6494c2010-01-28 17:12:36 +01003609 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003610 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3611 file, linenum, args[0]);
3612 err_code |= ERR_ALERT | ERR_FATAL;
3613 goto out;
3614 }
3615
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003616 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3617 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3618 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003619 err_code |= ERR_ALERT | ERR_FATAL;
3620 goto out;
3621 }
3622
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003623 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3624 * where force-persist is applied.
3625 */
3626 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003627
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003628 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003629 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003630 if (!strcmp(args[0], "force-persist")) {
3631 rule->type = PERSIST_TYPE_FORCE;
3632 } else {
3633 rule->type = PERSIST_TYPE_IGNORE;
3634 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003635 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003636 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003637 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003638 else if (!strcmp(args[0], "stick-table")) {
3639 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003640 struct proxy *other;
3641
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003642 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003643 if (other) {
3644 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3645 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3646 err_code |= ERR_ALERT | ERR_FATAL;
3647 goto out;
3648 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003649
Emeric Brun32da3c42010-09-23 18:39:19 +02003650 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003651 curproxy->table.type = (unsigned int)-1;
3652 while (*args[myidx]) {
3653 const char *err;
3654
3655 if (strcmp(args[myidx], "size") == 0) {
3656 myidx++;
3657 if (!*(args[myidx])) {
3658 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3659 file, linenum, args[myidx-1]);
3660 err_code |= ERR_ALERT | ERR_FATAL;
3661 goto out;
3662 }
3663 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3664 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3665 file, linenum, *err, args[myidx-1]);
3666 err_code |= ERR_ALERT | ERR_FATAL;
3667 goto out;
3668 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003669 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003670 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003671 else if (strcmp(args[myidx], "peers") == 0) {
3672 myidx++;
Godbach50523162013-12-11 19:48:57 +08003673 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003674 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3675 file, linenum, args[myidx-1]);
3676 err_code |= ERR_ALERT | ERR_FATAL;
3677 goto out;
Godbach50523162013-12-11 19:48:57 +08003678 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003679 curproxy->table.peers.name = strdup(args[myidx++]);
3680 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003681 else if (strcmp(args[myidx], "expire") == 0) {
3682 myidx++;
3683 if (!*(args[myidx])) {
3684 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3685 file, linenum, args[myidx-1]);
3686 err_code |= ERR_ALERT | ERR_FATAL;
3687 goto out;
3688 }
3689 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3690 if (err) {
3691 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3692 file, linenum, *err, args[myidx-1]);
3693 err_code |= ERR_ALERT | ERR_FATAL;
3694 goto out;
3695 }
3696 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003697 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003698 }
3699 else if (strcmp(args[myidx], "nopurge") == 0) {
3700 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003701 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003702 }
3703 else if (strcmp(args[myidx], "type") == 0) {
3704 myidx++;
3705 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3706 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3707 file, linenum, args[myidx]);
3708 err_code |= ERR_ALERT | ERR_FATAL;
3709 goto out;
3710 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003711 /* myidx already points to next arg */
3712 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003713 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003714 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003715 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003716
3717 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003718 nw = args[myidx];
3719 while (*nw) {
3720 /* the "store" keyword supports a comma-separated list */
3721 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003722 sa = NULL; /* store arg */
3723 while (*nw && *nw != ',') {
3724 if (*nw == '(') {
3725 *nw = 0;
3726 sa = ++nw;
3727 while (*nw != ')') {
3728 if (!*nw) {
3729 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3730 file, linenum, args[0], cw);
3731 err_code |= ERR_ALERT | ERR_FATAL;
3732 goto out;
3733 }
3734 nw++;
3735 }
3736 *nw = '\0';
3737 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003738 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003739 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003740 if (*nw)
3741 *nw++ = '\0';
3742 type = stktable_get_data_type(cw);
3743 if (type < 0) {
3744 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3745 file, linenum, args[0], cw);
3746 err_code |= ERR_ALERT | ERR_FATAL;
3747 goto out;
3748 }
Willy Tarreauac782882010-06-20 10:41:54 +02003749
3750 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3751 switch (err) {
3752 case PE_NONE: break;
3753 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003754 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3755 file, linenum, args[0], cw);
3756 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003757 break;
3758
3759 case PE_ARG_MISSING:
3760 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3761 file, linenum, args[0], cw);
3762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
3764
3765 case PE_ARG_NOT_USED:
3766 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3767 file, linenum, args[0], cw);
3768 err_code |= ERR_ALERT | ERR_FATAL;
3769 goto out;
3770
3771 default:
3772 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3773 file, linenum, args[0], cw);
3774 err_code |= ERR_ALERT | ERR_FATAL;
3775 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003776 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003777 }
3778 myidx++;
3779 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003780 else {
3781 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3782 file, linenum, args[myidx]);
3783 err_code |= ERR_ALERT | ERR_FATAL;
3784 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003785 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003786 }
3787
3788 if (!curproxy->table.size) {
3789 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3790 file, linenum);
3791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
3793 }
3794
3795 if (curproxy->table.type == (unsigned int)-1) {
3796 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3797 file, linenum);
3798 err_code |= ERR_ALERT | ERR_FATAL;
3799 goto out;
3800 }
3801 }
3802 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003803 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003804 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003805 int myidx = 0;
3806 const char *name = NULL;
3807 int flags;
3808
3809 if (curproxy == &defproxy) {
3810 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3811 err_code |= ERR_ALERT | ERR_FATAL;
3812 goto out;
3813 }
3814
3815 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3816 err_code |= ERR_WARN;
3817 goto out;
3818 }
3819
3820 myidx++;
3821 if ((strcmp(args[myidx], "store") == 0) ||
3822 (strcmp(args[myidx], "store-request") == 0)) {
3823 myidx++;
3824 flags = STK_IS_STORE;
3825 }
3826 else if (strcmp(args[myidx], "store-response") == 0) {
3827 myidx++;
3828 flags = STK_IS_STORE | STK_ON_RSP;
3829 }
3830 else if (strcmp(args[myidx], "match") == 0) {
3831 myidx++;
3832 flags = STK_IS_MATCH;
3833 }
3834 else if (strcmp(args[myidx], "on") == 0) {
3835 myidx++;
3836 flags = STK_IS_MATCH | STK_IS_STORE;
3837 }
3838 else {
3839 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
3842 }
3843
3844 if (*(args[myidx]) == 0) {
3845 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
3848 }
3849
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003850 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003851 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003852 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003853 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003854 err_code |= ERR_ALERT | ERR_FATAL;
3855 goto out;
3856 }
3857
3858 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003859 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3860 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3861 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003862 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003863 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003864 goto out;
3865 }
3866 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003867 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3868 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3869 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003870 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003871 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003872 goto out;
3873 }
3874 }
3875
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003876 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003877 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003878
Emeric Brunb982a3d2010-01-04 15:45:53 +01003879 if (strcmp(args[myidx], "table") == 0) {
3880 myidx++;
3881 name = args[myidx++];
3882 }
3883
Willy Tarreauef6494c2010-01-28 17:12:36 +01003884 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003885 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3886 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3887 file, linenum, args[0], errmsg);
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 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003892 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003893 else if (*(args[myidx])) {
3894 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3895 file, linenum, args[0], args[myidx]);
3896 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003897 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003898 goto out;
3899 }
Emeric Brun97679e72010-09-23 17:56:44 +02003900 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003901 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003902 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003903 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003904
Emeric Brunb982a3d2010-01-04 15:45:53 +01003905 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3906 rule->cond = cond;
3907 rule->expr = expr;
3908 rule->flags = flags;
3909 rule->table.name = name ? strdup(name) : NULL;
3910 LIST_INIT(&rule->list);
3911 if (flags & STK_ON_RSP)
3912 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3913 else
3914 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3915 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003916 else if (!strcmp(args[0], "stats")) {
3917 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3918 curproxy->uri_auth = NULL; /* we must detach from the default config */
3919
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003920 if (!*args[1]) {
3921 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003922 } else if (!strcmp(args[1], "admin")) {
3923 struct stats_admin_rule *rule;
3924
3925 if (curproxy == &defproxy) {
3926 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3927 err_code |= ERR_ALERT | ERR_FATAL;
3928 goto out;
3929 }
3930
3931 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3932 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3933 err_code |= ERR_ALERT | ERR_ABORT;
3934 goto out;
3935 }
3936
3937 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3938 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3939 file, linenum, args[0], args[1]);
3940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
3942 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003943 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3944 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3945 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
3948 }
3949
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003950 err_code |= warnif_cond_conflicts(cond,
3951 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3952 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003953
3954 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3955 rule->cond = cond;
3956 LIST_INIT(&rule->list);
3957 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003958 } else if (!strcmp(args[1], "uri")) {
3959 if (*(args[2]) == 0) {
3960 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003961 err_code |= ERR_ALERT | ERR_FATAL;
3962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003963 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3964 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003965 err_code |= ERR_ALERT | ERR_ABORT;
3966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003967 }
3968 } else if (!strcmp(args[1], "realm")) {
3969 if (*(args[2]) == 0) {
3970 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003971 err_code |= ERR_ALERT | ERR_FATAL;
3972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003973 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3974 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003975 err_code |= ERR_ALERT | ERR_ABORT;
3976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003977 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003978 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003979 unsigned interval;
3980
3981 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3982 if (err) {
3983 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3984 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003987 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3988 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003989 err_code |= ERR_ALERT | ERR_ABORT;
3990 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003991 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003992 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003993 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003994
3995 if (curproxy == &defproxy) {
3996 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
3999 }
4000
4001 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4002 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4003 err_code |= ERR_ALERT | ERR_ABORT;
4004 goto out;
4005 }
4006
Willy Tarreauff011f22011-01-06 17:51:27 +01004007 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
4008 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004009 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4010 file, linenum, args[0]);
4011 err_code |= ERR_WARN;
4012 }
4013
Willy Tarreauff011f22011-01-06 17:51:27 +01004014 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004015
Willy Tarreauff011f22011-01-06 17:51:27 +01004016 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004017 err_code |= ERR_ALERT | ERR_ABORT;
4018 goto out;
4019 }
4020
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004021 err_code |= warnif_cond_conflicts(rule->cond,
4022 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4023 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004024 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004025
Willy Tarreaubaaee002006-06-26 02:48:02 +02004026 } else if (!strcmp(args[1], "auth")) {
4027 if (*(args[2]) == 0) {
4028 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004029 err_code |= ERR_ALERT | ERR_FATAL;
4030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004031 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4032 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004033 err_code |= ERR_ALERT | ERR_ABORT;
4034 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004035 }
4036 } else if (!strcmp(args[1], "scope")) {
4037 if (*(args[2]) == 0) {
4038 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004041 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4042 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004043 err_code |= ERR_ALERT | ERR_ABORT;
4044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004045 }
4046 } else if (!strcmp(args[1], "enable")) {
4047 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4048 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004049 err_code |= ERR_ALERT | ERR_ABORT;
4050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004051 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004052 } else if (!strcmp(args[1], "hide-version")) {
4053 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4054 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004055 err_code |= ERR_ALERT | ERR_ABORT;
4056 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004057 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004058 } else if (!strcmp(args[1], "show-legends")) {
4059 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4060 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4061 err_code |= ERR_ALERT | ERR_ABORT;
4062 goto out;
4063 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004064 } else if (!strcmp(args[1], "show-node")) {
4065
4066 if (*args[2]) {
4067 int i;
4068 char c;
4069
4070 for (i=0; args[2][i]; i++) {
4071 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004072 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4073 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004074 break;
4075 }
4076
4077 if (!i || args[2][i]) {
4078 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4079 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4080 file, linenum, args[0], args[1]);
4081 err_code |= ERR_ALERT | ERR_FATAL;
4082 goto out;
4083 }
4084 }
4085
4086 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4087 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4088 err_code |= ERR_ALERT | ERR_ABORT;
4089 goto out;
4090 }
4091 } else if (!strcmp(args[1], "show-desc")) {
4092 char *desc = NULL;
4093
4094 if (*args[2]) {
4095 int i, len=0;
4096 char *d;
4097
Willy Tarreau348acfe2014-04-14 15:00:39 +02004098 for (i = 2; *args[i]; i++)
4099 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004100
4101 desc = d = (char *)calloc(1, len);
4102
Willy Tarreau348acfe2014-04-14 15:00:39 +02004103 d += snprintf(d, desc + len - d, "%s", args[2]);
4104 for (i = 3; *args[i]; i++)
4105 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004106 }
4107
4108 if (!*args[2] && !global.desc)
4109 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4110 file, linenum, args[1]);
4111 else {
4112 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4113 free(desc);
4114 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4115 err_code |= ERR_ALERT | ERR_ABORT;
4116 goto out;
4117 }
4118 free(desc);
4119 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004120 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004121stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004122 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 +01004123 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004126 }
4127 }
4128 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004129 int optnum;
4130
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004131 if (*(args[1]) == '\0') {
4132 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4133 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004136 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004137
4138 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4139 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004140 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4141 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4142 file, linenum, cfg_opts[optnum].name);
4143 err_code |= ERR_ALERT | ERR_FATAL;
4144 goto out;
4145 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004146 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4147 goto out;
4148
Willy Tarreau93893792009-07-23 13:19:11 +02004149 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4150 err_code |= ERR_WARN;
4151 goto out;
4152 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004153
Willy Tarreau3842f002009-06-14 11:39:52 +02004154 curproxy->no_options &= ~cfg_opts[optnum].val;
4155 curproxy->options &= ~cfg_opts[optnum].val;
4156
4157 switch (kwm) {
4158 case KWM_STD:
4159 curproxy->options |= cfg_opts[optnum].val;
4160 break;
4161 case KWM_NO:
4162 curproxy->no_options |= cfg_opts[optnum].val;
4163 break;
4164 case KWM_DEF: /* already cleared */
4165 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004166 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004167
Willy Tarreau93893792009-07-23 13:19:11 +02004168 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004169 }
4170 }
4171
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004172 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4173 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004174 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4175 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4176 file, linenum, cfg_opts2[optnum].name);
4177 err_code |= ERR_ALERT | ERR_FATAL;
4178 goto out;
4179 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004180 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4181 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004182 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4183 err_code |= ERR_WARN;
4184 goto out;
4185 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004186
Willy Tarreau3842f002009-06-14 11:39:52 +02004187 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4188 curproxy->options2 &= ~cfg_opts2[optnum].val;
4189
4190 switch (kwm) {
4191 case KWM_STD:
4192 curproxy->options2 |= cfg_opts2[optnum].val;
4193 break;
4194 case KWM_NO:
4195 curproxy->no_options2 |= cfg_opts2[optnum].val;
4196 break;
4197 case KWM_DEF: /* already cleared */
4198 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004199 }
Willy Tarreau93893792009-07-23 13:19:11 +02004200 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004201 }
4202 }
4203
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004204 /* HTTP options override each other. They can be cancelled using
4205 * "no option xxx" which only switches to default mode if the mode
4206 * was this one (useful for cancelling options set in defaults
4207 * sections).
4208 */
4209 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004210 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4211 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004212 if (kwm == KWM_STD) {
4213 curproxy->options &= ~PR_O_HTTP_MODE;
4214 curproxy->options |= PR_O_HTTP_PCL;
4215 goto out;
4216 }
4217 else if (kwm == KWM_NO) {
4218 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4219 curproxy->options &= ~PR_O_HTTP_MODE;
4220 goto out;
4221 }
4222 }
4223 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004224 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4225 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004226 if (kwm == KWM_STD) {
4227 curproxy->options &= ~PR_O_HTTP_MODE;
4228 curproxy->options |= PR_O_HTTP_FCL;
4229 goto out;
4230 }
4231 else if (kwm == KWM_NO) {
4232 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4233 curproxy->options &= ~PR_O_HTTP_MODE;
4234 goto out;
4235 }
4236 }
4237 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004238 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4239 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004240 if (kwm == KWM_STD) {
4241 curproxy->options &= ~PR_O_HTTP_MODE;
4242 curproxy->options |= PR_O_HTTP_SCL;
4243 goto out;
4244 }
4245 else if (kwm == KWM_NO) {
4246 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4247 curproxy->options &= ~PR_O_HTTP_MODE;
4248 goto out;
4249 }
4250 }
4251 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004252 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4253 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004254 if (kwm == KWM_STD) {
4255 curproxy->options &= ~PR_O_HTTP_MODE;
4256 curproxy->options |= PR_O_HTTP_KAL;
4257 goto out;
4258 }
4259 else if (kwm == KWM_NO) {
4260 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4261 curproxy->options &= ~PR_O_HTTP_MODE;
4262 goto out;
4263 }
4264 }
4265 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004266 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4267 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004268 if (kwm == KWM_STD) {
4269 curproxy->options &= ~PR_O_HTTP_MODE;
4270 curproxy->options |= PR_O_HTTP_TUN;
4271 goto out;
4272 }
4273 else if (kwm == KWM_NO) {
4274 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4275 curproxy->options &= ~PR_O_HTTP_MODE;
4276 goto out;
4277 }
4278 }
4279
Joseph Lynch726ab712015-05-11 23:25:34 -07004280 /* Redispatch can take an integer argument that control when the
4281 * resispatch occurs. All values are relative to the retries option.
4282 * This can be cancelled using "no option xxx".
4283 */
4284 if (strcmp(args[1], "redispatch") == 0) {
4285 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4286 err_code |= ERR_WARN;
4287 goto out;
4288 }
4289
4290 curproxy->no_options &= ~PR_O_REDISP;
4291 curproxy->options &= ~PR_O_REDISP;
4292
4293 switch (kwm) {
4294 case KWM_STD:
4295 curproxy->options |= PR_O_REDISP;
4296 curproxy->redispatch_after = -1;
4297 if(*args[2]) {
4298 curproxy->redispatch_after = atol(args[2]);
4299 }
4300 break;
4301 case KWM_NO:
4302 curproxy->no_options |= PR_O_REDISP;
4303 curproxy->redispatch_after = 0;
4304 break;
4305 case KWM_DEF: /* already cleared */
4306 break;
4307 }
4308 goto out;
4309 }
4310
Willy Tarreau3842f002009-06-14 11:39:52 +02004311 if (kwm != KWM_STD) {
4312 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004313 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004314 err_code |= ERR_ALERT | ERR_FATAL;
4315 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004316 }
4317
Emeric Brun3a058f32009-06-30 18:26:00 +02004318 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004319 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004320 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004321 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004322 if (*(args[2]) != '\0') {
4323 if (!strcmp(args[2], "clf")) {
4324 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004325 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004326 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004327 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004328 err_code |= ERR_ALERT | ERR_FATAL;
4329 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004330 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004331 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4332 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004333 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004334 if (curproxy->conf.logformat_string != default_http_log_format &&
4335 curproxy->conf.logformat_string != default_tcp_log_format &&
4336 curproxy->conf.logformat_string != clf_http_log_format)
4337 free(curproxy->conf.logformat_string);
4338 curproxy->conf.logformat_string = logformat;
4339
4340 free(curproxy->conf.lfs_file);
4341 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4342 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004343 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004344 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004345 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004346 if (curproxy->conf.logformat_string != default_http_log_format &&
4347 curproxy->conf.logformat_string != default_tcp_log_format &&
4348 curproxy->conf.logformat_string != clf_http_log_format)
4349 free(curproxy->conf.logformat_string);
4350 curproxy->conf.logformat_string = default_tcp_log_format;
4351
4352 free(curproxy->conf.lfs_file);
4353 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4354 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004355
4356 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4357 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004358 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004359 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004360 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004361 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004362 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004363
William Lallemanddf1425a2015-04-28 20:17:49 +02004364 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4365 goto out;
4366
Willy Tarreau13943ab2006-12-31 00:24:10 +01004367 if (curproxy->cap & PR_CAP_FE)
4368 curproxy->options |= PR_O_TCP_CLI_KA;
4369 if (curproxy->cap & PR_CAP_BE)
4370 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004371 }
4372 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004373 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004374 err_code |= ERR_WARN;
4375
Willy Tarreaubaaee002006-06-26 02:48:02 +02004376 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004377 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004378 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004379 curproxy->options2 &= ~PR_O2_CHK_ANY;
4380 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004381 if (!*args[2]) { /* no argument */
4382 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4383 curproxy->check_len = strlen(DEF_CHECK_REQ);
4384 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004385 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004386 curproxy->check_req = (char *)malloc(reqlen);
4387 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004388 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004389 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004390 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004391 if (*args[4])
4392 reqlen += strlen(args[4]);
4393 else
4394 reqlen += strlen("HTTP/1.0");
4395
4396 curproxy->check_req = (char *)malloc(reqlen);
4397 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004398 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004399 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004400 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4401 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004402 }
4403 else if (!strcmp(args[1], "ssl-hello-chk")) {
4404 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004405 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004406 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004407
Willy Tarreaua534fea2008-08-03 12:19:50 +02004408 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004409 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004410 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004411 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004412
4413 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004415 }
Willy Tarreau23677902007-05-08 23:50:35 +02004416 else if (!strcmp(args[1], "smtpchk")) {
4417 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004418 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004419 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004420 curproxy->options2 &= ~PR_O2_CHK_ANY;
4421 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004422
4423 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4424 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4425 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4426 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4427 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4428 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4429 curproxy->check_req = (char *)malloc(reqlen);
4430 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4431 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4432 } else {
4433 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4434 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4435 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4436 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4437 }
4438 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004439 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4440 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004441 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004442 else if (!strcmp(args[1], "pgsql-check")) {
4443 /* use PostgreSQL request to check servers' health */
4444 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4445 err_code |= ERR_WARN;
4446
4447 free(curproxy->check_req);
4448 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004449 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004450 curproxy->options2 |= PR_O2_PGSQL_CHK;
4451
4452 if (*(args[2])) {
4453 int cur_arg = 2;
4454
4455 while (*(args[cur_arg])) {
4456 if (strcmp(args[cur_arg], "user") == 0) {
4457 char * packet;
4458 uint32_t packet_len;
4459 uint32_t pv;
4460
4461 /* suboption header - needs additional argument for it */
4462 if (*(args[cur_arg+1]) == 0) {
4463 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4464 file, linenum, args[0], args[1], args[cur_arg]);
4465 err_code |= ERR_ALERT | ERR_FATAL;
4466 goto out;
4467 }
4468
4469 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4470 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4471 pv = htonl(0x30000); /* protocol version 3.0 */
4472
4473 packet = (char*) calloc(1, packet_len);
4474
4475 memcpy(packet + 4, &pv, 4);
4476
4477 /* copy "user" */
4478 memcpy(packet + 8, "user", 4);
4479
4480 /* copy username */
4481 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4482
4483 free(curproxy->check_req);
4484 curproxy->check_req = packet;
4485 curproxy->check_len = packet_len;
4486
4487 packet_len = htonl(packet_len);
4488 memcpy(packet, &packet_len, 4);
4489 cur_arg += 2;
4490 } else {
4491 /* unknown suboption - catchall */
4492 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4493 file, linenum, args[0], args[1]);
4494 err_code |= ERR_ALERT | ERR_FATAL;
4495 goto out;
4496 }
4497 } /* end while loop */
4498 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004499 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4500 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004501 }
4502
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004503 else if (!strcmp(args[1], "redis-check")) {
4504 /* use REDIS PING request to check servers' health */
4505 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4506 err_code |= ERR_WARN;
4507
4508 free(curproxy->check_req);
4509 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004510 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004511 curproxy->options2 |= PR_O2_REDIS_CHK;
4512
4513 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4514 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4515 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004516
4517 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4518 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004519 }
4520
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004521 else if (!strcmp(args[1], "mysql-check")) {
4522 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004523 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4524 err_code |= ERR_WARN;
4525
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004526 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004527 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004528 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004529 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004530
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004531 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004532 * const char mysql40_client_auth_pkt[] = {
4533 * "\x0e\x00\x00" // packet length
4534 * "\x01" // packet number
4535 * "\x00\x00" // client capabilities
4536 * "\x00\x00\x01" // max packet
4537 * "haproxy\x00" // username (null terminated string)
4538 * "\x00" // filler (always 0x00)
4539 * "\x01\x00\x00" // packet length
4540 * "\x00" // packet number
4541 * "\x01" // COM_QUIT command
4542 * };
4543 */
4544
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004545 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4546 * const char mysql41_client_auth_pkt[] = {
4547 * "\x0e\x00\x00\" // packet length
4548 * "\x01" // packet number
4549 * "\x00\x00\x00\x00" // client capabilities
4550 * "\x00\x00\x00\x01" // max packet
4551 * "\x21" // character set (UTF-8)
4552 * char[23] // All zeroes
4553 * "haproxy\x00" // username (null terminated string)
4554 * "\x00" // filler (always 0x00)
4555 * "\x01\x00\x00" // packet length
4556 * "\x00" // packet number
4557 * "\x01" // COM_QUIT command
4558 * };
4559 */
4560
4561
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004562 if (*(args[2])) {
4563 int cur_arg = 2;
4564
4565 while (*(args[cur_arg])) {
4566 if (strcmp(args[cur_arg], "user") == 0) {
4567 char *mysqluser;
4568 int packetlen, reqlen, userlen;
4569
4570 /* suboption header - needs additional argument for it */
4571 if (*(args[cur_arg+1]) == 0) {
4572 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4573 file, linenum, args[0], args[1], args[cur_arg]);
4574 err_code |= ERR_ALERT | ERR_FATAL;
4575 goto out;
4576 }
4577 mysqluser = args[cur_arg + 1];
4578 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004579
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004580 if (*(args[cur_arg+2])) {
4581 if (!strcmp(args[cur_arg+2], "post-41")) {
4582 packetlen = userlen + 7 + 27;
4583 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004584
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004585 free(curproxy->check_req);
4586 curproxy->check_req = (char *)calloc(1, reqlen);
4587 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004588
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004589 snprintf(curproxy->check_req, 4, "%c%c%c",
4590 ((unsigned char) packetlen & 0xff),
4591 ((unsigned char) (packetlen >> 8) & 0xff),
4592 ((unsigned char) (packetlen >> 16) & 0xff));
4593
4594 curproxy->check_req[3] = 1;
4595 curproxy->check_req[5] = 130;
4596 curproxy->check_req[11] = 1;
4597 curproxy->check_req[12] = 33;
4598 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4599 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4600 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4601 cur_arg += 3;
4602 } else {
4603 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4604 err_code |= ERR_ALERT | ERR_FATAL;
4605 goto out;
4606 }
4607 } else {
4608 packetlen = userlen + 7;
4609 reqlen = packetlen + 9;
4610
4611 free(curproxy->check_req);
4612 curproxy->check_req = (char *)calloc(1, reqlen);
4613 curproxy->check_len = reqlen;
4614
4615 snprintf(curproxy->check_req, 4, "%c%c%c",
4616 ((unsigned char) packetlen & 0xff),
4617 ((unsigned char) (packetlen >> 8) & 0xff),
4618 ((unsigned char) (packetlen >> 16) & 0xff));
4619
4620 curproxy->check_req[3] = 1;
4621 curproxy->check_req[5] = 128;
4622 curproxy->check_req[8] = 1;
4623 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4624 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4625 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4626 cur_arg += 2;
4627 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004628 } else {
4629 /* unknown suboption - catchall */
4630 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4631 file, linenum, args[0], args[1]);
4632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
4634 }
4635 } /* end while loop */
4636 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004637 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004638 else if (!strcmp(args[1], "ldap-check")) {
4639 /* use LDAP request to check servers' health */
4640 free(curproxy->check_req);
4641 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004642 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004643 curproxy->options2 |= PR_O2_LDAP_CHK;
4644
4645 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4646 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4647 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004648 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4649 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004650 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004651 else if (!strcmp(args[1], "tcp-check")) {
4652 /* use raw TCPCHK send/expect to check servers' health */
4653 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4654 err_code |= ERR_WARN;
4655
4656 free(curproxy->check_req);
4657 curproxy->check_req = NULL;
4658 curproxy->options2 &= ~PR_O2_CHK_ANY;
4659 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004660 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4661 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004662 }
Simon Horman98637e52014-06-20 12:30:16 +09004663 else if (!strcmp(args[1], "external-check")) {
4664 /* excute an external command to check servers' health */
4665 free(curproxy->check_req);
4666 curproxy->check_req = NULL;
4667 curproxy->options2 &= ~PR_O2_CHK_ANY;
4668 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004669 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4670 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004671 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004672 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004673 int cur_arg;
4674
4675 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4676 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004677 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004678
Willy Tarreau87cf5142011-08-19 22:57:24 +02004679 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004680
4681 free(curproxy->fwdfor_hdr_name);
4682 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4683 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4684
4685 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4686 cur_arg = 2;
4687 while (*(args[cur_arg])) {
4688 if (!strcmp(args[cur_arg], "except")) {
4689 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004690 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004691 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4692 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004693 err_code |= ERR_ALERT | ERR_FATAL;
4694 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004695 }
4696 /* flush useless bits */
4697 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004698 cur_arg += 2;
4699 } else if (!strcmp(args[cur_arg], "header")) {
4700 /* suboption header - needs additional argument for it */
4701 if (*(args[cur_arg+1]) == 0) {
4702 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4703 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004704 err_code |= ERR_ALERT | ERR_FATAL;
4705 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004706 }
4707 free(curproxy->fwdfor_hdr_name);
4708 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4709 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4710 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004711 } else if (!strcmp(args[cur_arg], "if-none")) {
4712 curproxy->options &= ~PR_O_FF_ALWAYS;
4713 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004714 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004715 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004716 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004717 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004718 err_code |= ERR_ALERT | ERR_FATAL;
4719 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004720 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004721 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004722 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004723 else if (!strcmp(args[1], "originalto")) {
4724 int cur_arg;
4725
4726 /* insert x-original-to field, but not for the IP address listed as an except.
4727 * set default options (ie: bitfield, header name, etc)
4728 */
4729
4730 curproxy->options |= PR_O_ORGTO;
4731
4732 free(curproxy->orgto_hdr_name);
4733 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4734 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4735
Willy Tarreau87cf5142011-08-19 22:57:24 +02004736 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004737 cur_arg = 2;
4738 while (*(args[cur_arg])) {
4739 if (!strcmp(args[cur_arg], "except")) {
4740 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004741 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 +02004742 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4743 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004744 err_code |= ERR_ALERT | ERR_FATAL;
4745 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004746 }
4747 /* flush useless bits */
4748 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4749 cur_arg += 2;
4750 } else if (!strcmp(args[cur_arg], "header")) {
4751 /* suboption header - needs additional argument for it */
4752 if (*(args[cur_arg+1]) == 0) {
4753 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4754 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004755 err_code |= ERR_ALERT | ERR_FATAL;
4756 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004757 }
4758 free(curproxy->orgto_hdr_name);
4759 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4760 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4761 cur_arg += 2;
4762 } else {
4763 /* unknown suboption - catchall */
4764 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4765 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004766 err_code |= ERR_ALERT | ERR_FATAL;
4767 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004768 }
4769 } /* end while loop */
4770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004771 else {
4772 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004773 err_code |= ERR_ALERT | ERR_FATAL;
4774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004775 }
Willy Tarreau93893792009-07-23 13:19:11 +02004776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004777 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004778 else if (!strcmp(args[0], "default_backend")) {
4779 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004780 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004781
4782 if (*(args[1]) == 0) {
4783 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004784 err_code |= ERR_ALERT | ERR_FATAL;
4785 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004786 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004787 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004788 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02004789
4790 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
4791 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004792 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004793 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004794 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004795 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004796
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004797 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4798 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 +01004799 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004800 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004801 /* enable reconnections to dispatch */
4802 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02004803
4804 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
4805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004806 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004807 else if (!strcmp(args[0], "http-check")) {
4808 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004809 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004810
4811 if (strcmp(args[1], "disable-on-404") == 0) {
4812 /* enable a graceful server shutdown on an HTTP 404 response */
4813 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02004814 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4815 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004816 }
Willy Tarreauef781042010-01-27 11:53:01 +01004817 else if (strcmp(args[1], "send-state") == 0) {
4818 /* enable emission of the apparent state of a server in HTTP checks */
4819 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02004820 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4821 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01004822 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004823 else if (strcmp(args[1], "expect") == 0) {
4824 const char *ptr_arg;
4825 int cur_arg;
4826
4827 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4828 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4829 err_code |= ERR_ALERT | ERR_FATAL;
4830 goto out;
4831 }
4832
4833 cur_arg = 2;
4834 /* consider exclamation marks, sole or at the beginning of a word */
4835 while (*(ptr_arg = args[cur_arg])) {
4836 while (*ptr_arg == '!') {
4837 curproxy->options2 ^= PR_O2_EXP_INV;
4838 ptr_arg++;
4839 }
4840 if (*ptr_arg)
4841 break;
4842 cur_arg++;
4843 }
4844 /* now ptr_arg points to the beginning of a word past any possible
4845 * exclamation mark, and cur_arg is the argument which holds this word.
4846 */
4847 if (strcmp(ptr_arg, "status") == 0) {
4848 if (!*(args[cur_arg + 1])) {
4849 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4850 file, linenum, args[0], args[1], ptr_arg);
4851 err_code |= ERR_ALERT | ERR_FATAL;
4852 goto out;
4853 }
4854 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004855 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004856 curproxy->expect_str = strdup(args[cur_arg + 1]);
4857 }
4858 else if (strcmp(ptr_arg, "string") == 0) {
4859 if (!*(args[cur_arg + 1])) {
4860 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4861 file, linenum, args[0], args[1], ptr_arg);
4862 err_code |= ERR_ALERT | ERR_FATAL;
4863 goto out;
4864 }
4865 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004866 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004867 curproxy->expect_str = strdup(args[cur_arg + 1]);
4868 }
4869 else if (strcmp(ptr_arg, "rstatus") == 0) {
4870 if (!*(args[cur_arg + 1])) {
4871 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4872 file, linenum, args[0], args[1], ptr_arg);
4873 err_code |= ERR_ALERT | ERR_FATAL;
4874 goto out;
4875 }
4876 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004877 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004878 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004879 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004880 free(curproxy->expect_regex);
4881 curproxy->expect_regex = NULL;
4882 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004883 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004884 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4885 error = NULL;
4886 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4887 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4888 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4889 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004890 err_code |= ERR_ALERT | ERR_FATAL;
4891 goto out;
4892 }
4893 }
4894 else if (strcmp(ptr_arg, "rstring") == 0) {
4895 if (!*(args[cur_arg + 1])) {
4896 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4897 file, linenum, args[0], args[1], ptr_arg);
4898 err_code |= ERR_ALERT | ERR_FATAL;
4899 goto out;
4900 }
4901 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004902 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004903 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004904 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004905 free(curproxy->expect_regex);
4906 curproxy->expect_regex = NULL;
4907 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004908 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004909 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4910 error = NULL;
4911 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4912 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4913 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4914 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004915 err_code |= ERR_ALERT | ERR_FATAL;
4916 goto out;
4917 }
4918 }
4919 else {
4920 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4921 file, linenum, args[0], args[1], ptr_arg);
4922 err_code |= ERR_ALERT | ERR_FATAL;
4923 goto out;
4924 }
4925 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004926 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004927 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 +02004928 err_code |= ERR_ALERT | ERR_FATAL;
4929 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004930 }
4931 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004932 else if (!strcmp(args[0], "tcp-check")) {
4933 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4934 err_code |= ERR_WARN;
4935
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004936 if (strcmp(args[1], "comment") == 0) {
4937 int cur_arg;
4938 struct tcpcheck_rule *tcpcheck;
4939
4940 cur_arg = 1;
4941 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4942 tcpcheck->action = TCPCHK_ACT_COMMENT;
4943
4944 if (!*args[cur_arg + 1]) {
4945 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4946 file, linenum, args[cur_arg]);
4947 err_code |= ERR_ALERT | ERR_FATAL;
4948 goto out;
4949 }
4950
4951 tcpcheck->comment = strdup(args[cur_arg + 1]);
4952
4953 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02004954 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4955 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004956 }
4957 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004958 const char *ptr_arg;
4959 int cur_arg;
4960 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004961
4962 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02004963 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
4964 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
4965 tcpcheck->action == TCPCHK_ACT_COMMENT) {
4966 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
4967 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004968
Willy Tarreau5581c272015-05-13 12:24:53 +02004969 if (&tcpcheck->list != &curproxy->tcpcheck_rules
4970 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4971 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4972 file, linenum);
4973 err_code |= ERR_ALERT | ERR_FATAL;
4974 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004975 }
4976
4977 cur_arg = 2;
4978 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4979 tcpcheck->action = TCPCHK_ACT_CONNECT;
4980
4981 /* parsing each parameters to fill up the rule */
4982 while (*(ptr_arg = args[cur_arg])) {
4983 /* tcp port */
4984 if (strcmp(args[cur_arg], "port") == 0) {
4985 if ( (atol(args[cur_arg + 1]) > 65535) ||
4986 (atol(args[cur_arg + 1]) < 1) ){
4987 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4988 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4989 err_code |= ERR_ALERT | ERR_FATAL;
4990 goto out;
4991 }
4992 tcpcheck->port = atol(args[cur_arg + 1]);
4993 cur_arg += 2;
4994 }
4995 /* send proxy protocol */
4996 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4997 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4998 cur_arg++;
4999 }
5000#ifdef USE_OPENSSL
5001 else if (strcmp(args[cur_arg], "ssl") == 0) {
5002 curproxy->options |= PR_O_TCPCHK_SSL;
5003 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5004 cur_arg++;
5005 }
5006#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005007 /* comment for this tcpcheck line */
5008 else if (strcmp(args[cur_arg], "comment") == 0) {
5009 if (!*args[cur_arg + 1]) {
5010 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5011 file, linenum, args[cur_arg]);
5012 err_code |= ERR_ALERT | ERR_FATAL;
5013 goto out;
5014 }
5015 tcpcheck->comment = strdup(args[cur_arg + 1]);
5016 cur_arg += 2;
5017 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005018 else {
5019#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005020 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 +01005021#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005022 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 +01005023#endif /* USE_OPENSSL */
5024 file, linenum, args[0], args[1], args[cur_arg]);
5025 err_code |= ERR_ALERT | ERR_FATAL;
5026 goto out;
5027 }
5028
5029 }
5030
5031 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5032 }
5033 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005034 if (! *(args[2]) ) {
5035 /* SEND string expected */
5036 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5037 file, linenum, args[0], args[1], args[2]);
5038 err_code |= ERR_ALERT | ERR_FATAL;
5039 goto out;
5040 } else {
5041 struct tcpcheck_rule *tcpcheck;
5042
5043 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5044
5045 tcpcheck->action = TCPCHK_ACT_SEND;
5046 tcpcheck->string_len = strlen(args[2]);
5047 tcpcheck->string = strdup(args[2]);
5048 tcpcheck->expect_regex = NULL;
5049
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005050 /* comment for this tcpcheck line */
5051 if (strcmp(args[3], "comment") == 0) {
5052 if (!*args[4]) {
5053 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5054 file, linenum, args[3]);
5055 err_code |= ERR_ALERT | ERR_FATAL;
5056 goto out;
5057 }
5058 tcpcheck->comment = strdup(args[4]);
5059 }
5060
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005061 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5062 }
5063 }
5064 else if (strcmp(args[1], "send-binary") == 0) {
5065 if (! *(args[2]) ) {
5066 /* SEND binary string expected */
5067 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5068 file, linenum, args[0], args[1], args[2]);
5069 err_code |= ERR_ALERT | ERR_FATAL;
5070 goto out;
5071 } else {
5072 struct tcpcheck_rule *tcpcheck;
5073 char *err = NULL;
5074
5075 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5076
5077 tcpcheck->action = TCPCHK_ACT_SEND;
5078 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5079 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5080 file, linenum, args[0], args[1], args[2], err);
5081 err_code |= ERR_ALERT | ERR_FATAL;
5082 goto out;
5083 }
5084 tcpcheck->expect_regex = NULL;
5085
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005086 /* comment for this tcpcheck line */
5087 if (strcmp(args[3], "comment") == 0) {
5088 if (!*args[4]) {
5089 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5090 file, linenum, args[3]);
5091 err_code |= ERR_ALERT | ERR_FATAL;
5092 goto out;
5093 }
5094 tcpcheck->comment = strdup(args[4]);
5095 }
5096
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005097 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5098 }
5099 }
5100 else if (strcmp(args[1], "expect") == 0) {
5101 const char *ptr_arg;
5102 int cur_arg;
5103 int inverse = 0;
5104
5105 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5106 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
5109 }
5110
5111 cur_arg = 2;
5112 /* consider exclamation marks, sole or at the beginning of a word */
5113 while (*(ptr_arg = args[cur_arg])) {
5114 while (*ptr_arg == '!') {
5115 inverse = !inverse;
5116 ptr_arg++;
5117 }
5118 if (*ptr_arg)
5119 break;
5120 cur_arg++;
5121 }
5122 /* now ptr_arg points to the beginning of a word past any possible
5123 * exclamation mark, and cur_arg is the argument which holds this word.
5124 */
5125 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005126 struct tcpcheck_rule *tcpcheck;
5127 char *err = NULL;
5128
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005129 if (!*(args[cur_arg + 1])) {
5130 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5131 file, linenum, args[0], args[1], ptr_arg);
5132 err_code |= ERR_ALERT | ERR_FATAL;
5133 goto out;
5134 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005135
5136 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5137
5138 tcpcheck->action = TCPCHK_ACT_EXPECT;
5139 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5140 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5141 file, linenum, args[0], args[1], args[2], err);
5142 err_code |= ERR_ALERT | ERR_FATAL;
5143 goto out;
5144 }
5145 tcpcheck->expect_regex = NULL;
5146 tcpcheck->inverse = inverse;
5147
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005148 /* tcpcheck comment */
5149 cur_arg += 2;
5150 if (strcmp(args[cur_arg], "comment") == 0) {
5151 if (!*args[cur_arg + 1]) {
5152 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5153 file, linenum, args[cur_arg + 1]);
5154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
5156 }
5157 tcpcheck->comment = strdup(args[cur_arg + 1]);
5158 }
5159
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005160 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5161 }
5162 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005163 struct tcpcheck_rule *tcpcheck;
5164
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005165 if (!*(args[cur_arg + 1])) {
5166 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5167 file, linenum, args[0], args[1], ptr_arg);
5168 err_code |= ERR_ALERT | ERR_FATAL;
5169 goto out;
5170 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005171
5172 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5173
5174 tcpcheck->action = TCPCHK_ACT_EXPECT;
5175 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5176 tcpcheck->string = strdup(args[cur_arg + 1]);
5177 tcpcheck->expect_regex = NULL;
5178 tcpcheck->inverse = inverse;
5179
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005180 /* tcpcheck comment */
5181 cur_arg += 2;
5182 if (strcmp(args[cur_arg], "comment") == 0) {
5183 if (!*args[cur_arg + 1]) {
5184 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5185 file, linenum, args[cur_arg + 1]);
5186 err_code |= ERR_ALERT | ERR_FATAL;
5187 goto out;
5188 }
5189 tcpcheck->comment = strdup(args[cur_arg + 1]);
5190 }
5191
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005192 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5193 }
5194 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005195 struct tcpcheck_rule *tcpcheck;
5196
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005197 if (!*(args[cur_arg + 1])) {
5198 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5199 file, linenum, args[0], args[1], ptr_arg);
5200 err_code |= ERR_ALERT | ERR_FATAL;
5201 goto out;
5202 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005203
5204 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5205
5206 tcpcheck->action = TCPCHK_ACT_EXPECT;
5207 tcpcheck->string_len = 0;
5208 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005209 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5210 error = NULL;
5211 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5212 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5213 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5214 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005215 err_code |= ERR_ALERT | ERR_FATAL;
5216 goto out;
5217 }
5218 tcpcheck->inverse = inverse;
5219
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005220 /* tcpcheck comment */
5221 cur_arg += 2;
5222 if (strcmp(args[cur_arg], "comment") == 0) {
5223 if (!*args[cur_arg + 1]) {
5224 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5225 file, linenum, args[cur_arg + 1]);
5226 err_code |= ERR_ALERT | ERR_FATAL;
5227 goto out;
5228 }
5229 tcpcheck->comment = strdup(args[cur_arg + 1]);
5230 }
5231
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005232 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5233 }
5234 else {
5235 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5236 file, linenum, args[0], args[1], ptr_arg);
5237 err_code |= ERR_ALERT | ERR_FATAL;
5238 goto out;
5239 }
5240 }
5241 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005242 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005243 err_code |= ERR_ALERT | ERR_FATAL;
5244 goto out;
5245 }
5246 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005247 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005248 if (curproxy == &defproxy) {
5249 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005250 err_code |= ERR_ALERT | ERR_FATAL;
5251 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005252 }
5253
Willy Tarreaub80c2302007-11-30 20:51:32 +01005254 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005255 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005256
5257 if (strcmp(args[1], "fail") == 0) {
5258 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005259 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005260 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5261 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005262 err_code |= ERR_ALERT | ERR_FATAL;
5263 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005264 }
5265
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005266 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5267 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5268 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005269 err_code |= ERR_ALERT | ERR_FATAL;
5270 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005271 }
5272 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5273 }
5274 else {
5275 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005276 err_code |= ERR_ALERT | ERR_FATAL;
5277 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005278 }
5279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005280#ifdef TPROXY
5281 else if (!strcmp(args[0], "transparent")) {
5282 /* enable transparent proxy connections */
5283 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005284 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005286 }
5287#endif
5288 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005289 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005290 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005291
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292 if (*(args[1]) == 0) {
5293 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005294 err_code |= ERR_ALERT | ERR_FATAL;
5295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296 }
5297 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005298 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005300 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005301 else if (!strcmp(args[0], "backlog")) { /* backlog */
5302 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005303 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005304
5305 if (*(args[1]) == 0) {
5306 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005307 err_code |= ERR_ALERT | ERR_FATAL;
5308 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005309 }
5310 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005311 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5312 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005313 }
Willy Tarreau86034312006-12-29 00:10:33 +01005314 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005315 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005316 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005317
Willy Tarreau86034312006-12-29 00:10:33 +01005318 if (*(args[1]) == 0) {
5319 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005320 err_code |= ERR_ALERT | ERR_FATAL;
5321 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005322 }
5323 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005324 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5325 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005326 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005327 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5328 if (*(args[1]) == 0) {
5329 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005330 err_code |= ERR_ALERT | ERR_FATAL;
5331 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005332 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005333 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5334 if (err) {
5335 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5336 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005337 err_code |= ERR_ALERT | ERR_FATAL;
5338 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005339 }
5340 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005341 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5342 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005343 }
5344 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005345 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005346 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005347 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005348
Willy Tarreaubaaee002006-06-26 02:48:02 +02005349 if (curproxy == &defproxy) {
5350 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005351 err_code |= ERR_ALERT | ERR_FATAL;
5352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005353 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005354 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005355 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005356
Willy Tarreau902636f2013-03-10 19:44:48 +01005357 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005358 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005359 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005360 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005361 goto out;
5362 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005363
5364 proto = protocol_by_family(sk->ss_family);
5365 if (!proto || !proto->connect) {
5366 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5367 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005368 err_code |= ERR_ALERT | ERR_FATAL;
5369 goto out;
5370 }
5371
5372 if (port1 != port2) {
5373 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5374 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005375 err_code |= ERR_ALERT | ERR_FATAL;
5376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005377 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005378
5379 if (!port1) {
5380 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5381 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005382 err_code |= ERR_ALERT | ERR_FATAL;
5383 goto out;
5384 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005385
William Lallemanddf1425a2015-04-28 20:17:49 +02005386 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5387 goto out;
5388
Willy Tarreaud5191e72010-02-09 20:50:45 +01005389 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005390 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005391 }
5392 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005393 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005394 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005395
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005396 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5397 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005398 err_code |= ERR_ALERT | ERR_FATAL;
5399 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005400 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005401 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005402 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005403 /**
5404 * The syntax for hash-type config element is
5405 * hash-type {map-based|consistent} [[<algo>] avalanche]
5406 *
5407 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5408 */
5409 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005410
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005411 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5412 err_code |= ERR_WARN;
5413
5414 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005415 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5416 }
5417 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005418 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5419 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005420 else if (strcmp(args[1], "avalanche") == 0) {
5421 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]);
5422 err_code |= ERR_ALERT | ERR_FATAL;
5423 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005424 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005425 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005426 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005427 err_code |= ERR_ALERT | ERR_FATAL;
5428 goto out;
5429 }
Bhaskar98634f02013-10-29 23:30:51 -04005430
5431 /* set the hash function to use */
5432 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005433 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005434 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005435
5436 /* if consistent with no argument, then avalanche modifier is also applied */
5437 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5438 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005439 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005440 /* set the hash function */
5441 if (!strcmp(args[2], "sdbm")) {
5442 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5443 }
5444 else if (!strcmp(args[2], "djb2")) {
5445 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005446 }
5447 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005448 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005449 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005450 else if (!strcmp(args[2], "crc32")) {
5451 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5452 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005453 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005454 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 -05005455 err_code |= ERR_ALERT | ERR_FATAL;
5456 goto out;
5457 }
5458
5459 /* set the hash modifier */
5460 if (!strcmp(args[3], "avalanche")) {
5461 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5462 }
5463 else if (*args[3]) {
5464 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5465 err_code |= ERR_ALERT | ERR_FATAL;
5466 goto out;
5467 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005468 }
William Lallemanda73203e2012-03-12 12:48:57 +01005469 }
William Lallemanda73203e2012-03-12 12:48:57 +01005470 else if (strcmp(args[0], "unique-id-format") == 0) {
5471 if (!*(args[1])) {
5472 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5473 err_code |= ERR_ALERT | ERR_FATAL;
5474 goto out;
5475 }
William Lallemand3203ff42012-11-11 17:30:56 +01005476 if (*(args[2])) {
5477 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5478 err_code |= ERR_ALERT | ERR_FATAL;
5479 goto out;
5480 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005481 free(curproxy->conf.uniqueid_format_string);
5482 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005483
Willy Tarreau62a61232013-04-12 18:13:46 +02005484 free(curproxy->conf.uif_file);
5485 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5486 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005487 }
William Lallemanda73203e2012-03-12 12:48:57 +01005488
5489 else if (strcmp(args[0], "unique-id-header") == 0) {
5490 if (!*(args[1])) {
5491 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5492 err_code |= ERR_ALERT | ERR_FATAL;
5493 goto out;
5494 }
5495 free(curproxy->header_unique_id);
5496 curproxy->header_unique_id = strdup(args[1]);
5497 }
5498
William Lallemand723b73a2012-02-08 16:37:49 +01005499 else if (strcmp(args[0], "log-format") == 0) {
5500 if (!*(args[1])) {
5501 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5502 err_code |= ERR_ALERT | ERR_FATAL;
5503 goto out;
5504 }
William Lallemand3203ff42012-11-11 17:30:56 +01005505 if (*(args[2])) {
5506 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5507 err_code |= ERR_ALERT | ERR_FATAL;
5508 goto out;
5509 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005510
Willy Tarreau62a61232013-04-12 18:13:46 +02005511 if (curproxy->conf.logformat_string != default_http_log_format &&
5512 curproxy->conf.logformat_string != default_tcp_log_format &&
5513 curproxy->conf.logformat_string != clf_http_log_format)
5514 free(curproxy->conf.logformat_string);
5515 curproxy->conf.logformat_string = strdup(args[1]);
5516
5517 free(curproxy->conf.lfs_file);
5518 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5519 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005520
5521 /* get a chance to improve log-format error reporting by
5522 * reporting the correct line-number when possible.
5523 */
5524 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5525 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5526 file, linenum, curproxy->id);
5527 err_code |= ERR_WARN;
5528 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005529 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005530 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5531 if (*(args[1]) == 0) {
5532 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5533 err_code |= ERR_ALERT | ERR_FATAL;
5534 goto out;
5535 }
5536 free(curproxy->log_tag);
5537 curproxy->log_tag = strdup(args[1]);
5538 }
William Lallemand0f99e342011-10-12 17:50:54 +02005539 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5540 /* delete previous herited or defined syslog servers */
5541 struct logsrv *back;
5542
5543 if (*(args[1]) != 0) {
5544 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5545 err_code |= ERR_ALERT | ERR_FATAL;
5546 goto out;
5547 }
5548
William Lallemand723b73a2012-02-08 16:37:49 +01005549 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5550 LIST_DEL(&tmplogsrv->list);
5551 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005552 }
5553 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005554 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005555 struct logsrv *logsrv;
5556
Willy Tarreaubaaee002006-06-26 02:48:02 +02005557 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005558 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005559 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005560 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005561 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005562 LIST_INIT(&node->list);
5563 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5564 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005565 }
5566 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005567 struct sockaddr_storage *sk;
5568 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005569 int arg = 0;
5570 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005571
5572 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005573
Willy Tarreau18324f52014-06-27 18:10:07 +02005574 /* just after the address, a length may be specified */
5575 if (strcmp(args[arg+2], "len") == 0) {
5576 len = atoi(args[arg+3]);
5577 if (len < 80 || len > 65535) {
5578 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5579 file, linenum, args[arg+3]);
5580 err_code |= ERR_ALERT | ERR_FATAL;
5581 goto out;
5582 }
5583 logsrv->maxlen = len;
5584
5585 /* skip these two args */
5586 arg += 2;
5587 }
5588 else
5589 logsrv->maxlen = MAX_SYSLOG_LEN;
5590
5591 if (logsrv->maxlen > global.max_syslog_len) {
5592 global.max_syslog_len = logsrv->maxlen;
5593 logline = realloc(logline, global.max_syslog_len + 1);
5594 }
5595
William Lallemanddf1425a2015-04-28 20:17:49 +02005596 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5597 goto out;
5598
Willy Tarreau18324f52014-06-27 18:10:07 +02005599 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005600 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005601 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005602 err_code |= ERR_ALERT | ERR_FATAL;
5603 goto out;
5604
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605 }
5606
William Lallemand0f99e342011-10-12 17:50:54 +02005607 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005608 if (*(args[arg+3])) {
5609 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005610 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005611 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005612 err_code |= ERR_ALERT | ERR_FATAL;
5613 goto out;
5614
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615 }
5616 }
5617
William Lallemand0f99e342011-10-12 17:50:54 +02005618 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005619 if (*(args[arg+4])) {
5620 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005621 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005622 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005623 err_code |= ERR_ALERT | ERR_FATAL;
5624 goto out;
5625
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005626 }
5627 }
5628
Willy Tarreau902636f2013-03-10 19:44:48 +01005629 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005630 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005631 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005632 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005633 goto out;
5634 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005635
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005636 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005637
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005638 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005639 if (port1 != port2) {
5640 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5641 file, linenum, args[0], args[1]);
5642 err_code |= ERR_ALERT | ERR_FATAL;
5643 goto out;
5644 }
5645
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005646 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005647 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005648 }
William Lallemand0f99e342011-10-12 17:50:54 +02005649
5650 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005651 }
5652 else {
5653 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5654 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005655 err_code |= ERR_ALERT | ERR_FATAL;
5656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005657 }
5658 }
5659 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005660 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005661 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005662 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005663 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005664
Willy Tarreau977b8e42006-12-29 14:19:17 +01005665 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005666 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005667
Willy Tarreaubaaee002006-06-26 02:48:02 +02005668 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005669 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5670 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005671 err_code |= ERR_ALERT | ERR_FATAL;
5672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005673 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005674
5675 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005676 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5677 free(curproxy->conn_src.iface_name);
5678 curproxy->conn_src.iface_name = NULL;
5679 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005680
Willy Tarreau902636f2013-03-10 19:44:48 +01005681 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005682 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005683 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005684 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005685 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005686 goto out;
5687 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005688
5689 proto = protocol_by_family(sk->ss_family);
5690 if (!proto || !proto->connect) {
5691 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005692 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005693 err_code |= ERR_ALERT | ERR_FATAL;
5694 goto out;
5695 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005696
5697 if (port1 != port2) {
5698 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5699 file, linenum, args[0], args[1]);
5700 err_code |= ERR_ALERT | ERR_FATAL;
5701 goto out;
5702 }
5703
Willy Tarreauef9a3602012-12-08 22:29:20 +01005704 curproxy->conn_src.source_addr = *sk;
5705 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005706
5707 cur_arg = 2;
5708 while (*(args[cur_arg])) {
5709 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005710#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5711#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005712 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005713 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5714 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005715 err_code |= ERR_ALERT | ERR_FATAL;
5716 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005717 }
5718#endif
5719 if (!*args[cur_arg + 1]) {
5720 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5721 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005722 err_code |= ERR_ALERT | ERR_FATAL;
5723 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005724 }
5725
5726 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005727 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5728 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005729 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005730 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5731 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005732 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5733 char *name, *end;
5734
5735 name = args[cur_arg+1] + 7;
5736 while (isspace(*name))
5737 name++;
5738
5739 end = name;
5740 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5741 end++;
5742
Willy Tarreauef9a3602012-12-08 22:29:20 +01005743 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5744 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5745 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5746 curproxy->conn_src.bind_hdr_len = end - name;
5747 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5748 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5749 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005750
5751 /* now look for an occurrence number */
5752 while (isspace(*end))
5753 end++;
5754 if (*end == ',') {
5755 end++;
5756 name = end;
5757 if (*end == '-')
5758 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005759 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005760 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005761 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005762 }
5763
Willy Tarreauef9a3602012-12-08 22:29:20 +01005764 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005765 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5766 " occurrences values smaller than %d.\n",
5767 file, linenum, MAX_HDR_HISTORY);
5768 err_code |= ERR_ALERT | ERR_FATAL;
5769 goto out;
5770 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005771 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005772 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005773
Willy Tarreau902636f2013-03-10 19:44:48 +01005774 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005775 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005776 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005777 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005778 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005779 goto out;
5780 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005781
5782 proto = protocol_by_family(sk->ss_family);
5783 if (!proto || !proto->connect) {
5784 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5785 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005786 err_code |= ERR_ALERT | ERR_FATAL;
5787 goto out;
5788 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005789
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005790 if (port1 != port2) {
5791 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5792 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005793 err_code |= ERR_ALERT | ERR_FATAL;
5794 goto out;
5795 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005796 curproxy->conn_src.tproxy_addr = *sk;
5797 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005798 }
5799 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005800#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005801 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005802#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005803#else /* no TPROXY support */
5804 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005805 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005806 err_code |= ERR_ALERT | ERR_FATAL;
5807 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005808#endif
5809 cur_arg += 2;
5810 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005811 }
5812
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005813 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5814#ifdef SO_BINDTODEVICE
5815 if (!*args[cur_arg + 1]) {
5816 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5817 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005818 err_code |= ERR_ALERT | ERR_FATAL;
5819 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005820 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005821 free(curproxy->conn_src.iface_name);
5822 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5823 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005824 global.last_checks |= LSTCHK_NETADM;
5825#else
5826 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5827 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005828 err_code |= ERR_ALERT | ERR_FATAL;
5829 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005830#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005831 cur_arg += 2;
5832 continue;
5833 }
5834 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005835 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005836 err_code |= ERR_ALERT | ERR_FATAL;
5837 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005838 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005839 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005840 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5841 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5842 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005843 err_code |= ERR_ALERT | ERR_FATAL;
5844 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005845 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005846 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005847 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005848 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5849 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005850 err_code |= ERR_ALERT | ERR_FATAL;
5851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005852 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005853
5854 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005855 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005856 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005857 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005859 }
5860 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005861 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005862 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005863 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005864 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005866 }
5867 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005868 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005869 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005870 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005871 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005873 }
5874 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005875 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005876 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005877 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005878 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005880 }
5881 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005882 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005883 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005884 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005885 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005887 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005888 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005889 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005890 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005891 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005892 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005893 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005894 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005895 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005896 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005897 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5898 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005899 err_code |= ERR_ALERT | ERR_FATAL;
5900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005901 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005902
5903 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005904 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005905 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005906 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005908 }
5909 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005910 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005911 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005912 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005913 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005915 }
5916 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005917 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005918 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005919 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005920 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005922 }
5923 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005924 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005925 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005926 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005927 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005929 }
5930 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005931 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005932 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005933 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005934 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005936 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005937 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005938 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005939 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005940 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005941 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005942 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005943 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005944 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005945 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005946
Willy Tarreaubaaee002006-06-26 02:48:02 +02005947 if (curproxy == &defproxy) {
5948 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005949 err_code |= ERR_ALERT | ERR_FATAL;
5950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005951 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005952 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005953 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005954
Willy Tarreaubaaee002006-06-26 02:48:02 +02005955 if (*(args[1]) == 0) {
5956 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005957 err_code |= ERR_ALERT | ERR_FATAL;
5958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005959 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005960
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005961 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005962 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5963 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5964 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005965 err_code |= ERR_ALERT | ERR_FATAL;
5966 goto out;
5967 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005968 err_code |= warnif_cond_conflicts(cond,
5969 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5970 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005971 }
5972 else if (*args[2]) {
5973 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5974 file, linenum, args[0], args[2]);
5975 err_code |= ERR_ALERT | ERR_FATAL;
5976 goto out;
5977 }
5978
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005979 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005980 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005981 wl->s = strdup(args[1]);
5982 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005983 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005984 }
5985 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005986 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005987 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5988 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005989 err_code |= ERR_ALERT | ERR_FATAL;
5990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005991 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005992
Willy Tarreauade5ec42010-01-28 19:33:49 +01005993 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005994 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005995 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005996 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005998 }
5999 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006000 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006001 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006002 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006003 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006004 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006005 }
6006 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006007 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006008 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006009 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006010 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006012 }
6013 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006014 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006015 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6016 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006017 err_code |= ERR_ALERT | ERR_FATAL;
6018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006019 }
6020
Willy Tarreauade5ec42010-01-28 19:33:49 +01006021 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006022 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006023 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006024 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006026 }
6027 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006028 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006029 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006030 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006031 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006033 }
6034 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006035 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006036 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006037 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006038 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006040 }
6041 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006042 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006043
Willy Tarreaubaaee002006-06-26 02:48:02 +02006044 if (curproxy == &defproxy) {
6045 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006046 err_code |= ERR_ALERT | ERR_FATAL;
6047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006048 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006049 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006050 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006051
Willy Tarreaubaaee002006-06-26 02:48:02 +02006052 if (*(args[1]) == 0) {
6053 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006054 err_code |= ERR_ALERT | ERR_FATAL;
6055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006056 }
6057
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006058 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006059 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6060 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6061 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006062 err_code |= ERR_ALERT | ERR_FATAL;
6063 goto out;
6064 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006065 err_code |= warnif_cond_conflicts(cond,
6066 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6067 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006068 }
6069 else if (*args[2]) {
6070 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6071 file, linenum, args[0], args[2]);
6072 err_code |= ERR_ALERT | ERR_FATAL;
6073 goto out;
6074 }
6075
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006076 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006077 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006078 wl->s = strdup(args[1]);
6079 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006080 }
6081 else if (!strcmp(args[0], "errorloc") ||
6082 !strcmp(args[0], "errorloc302") ||
6083 !strcmp(args[0], "errorloc303")) { /* error location */
6084 int errnum, errlen;
6085 char *err;
6086
Willy Tarreau977b8e42006-12-29 14:19:17 +01006087 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006088 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006089
Willy Tarreaubaaee002006-06-26 02:48:02 +02006090 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006091 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006092 err_code |= ERR_ALERT | ERR_FATAL;
6093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006094 }
6095
6096 errnum = atol(args[1]);
6097 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006098 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6099 err = malloc(errlen);
6100 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006101 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006102 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6103 err = malloc(errlen);
6104 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006105 }
6106
Willy Tarreau0f772532006-12-23 20:51:41 +01006107 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6108 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006109 chunk_destroy(&curproxy->errmsg[rc]);
6110 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006111 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006112 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006113 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006114
6115 if (rc >= HTTP_ERR_SIZE) {
6116 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
6117 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006118 free(err);
6119 }
6120 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006121 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6122 int errnum, errlen, fd;
6123 char *err;
6124 struct stat stat;
6125
6126 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006127 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006128
6129 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006130 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006131 err_code |= ERR_ALERT | ERR_FATAL;
6132 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006133 }
6134
6135 fd = open(args[2], O_RDONLY);
6136 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6137 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6138 file, linenum, args[2], args[1]);
6139 if (fd >= 0)
6140 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006141 err_code |= ERR_ALERT | ERR_FATAL;
6142 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006143 }
6144
Willy Tarreau27a674e2009-08-17 07:23:33 +02006145 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006146 errlen = stat.st_size;
6147 } else {
6148 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006149 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006150 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006151 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006152 }
6153
6154 err = malloc(errlen); /* malloc() must succeed during parsing */
6155 errnum = read(fd, err, errlen);
6156 if (errnum != errlen) {
6157 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6158 file, linenum, args[2], args[1]);
6159 close(fd);
6160 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006161 err_code |= ERR_ALERT | ERR_FATAL;
6162 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006163 }
6164 close(fd);
6165
6166 errnum = atol(args[1]);
6167 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6168 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006169 chunk_destroy(&curproxy->errmsg[rc]);
6170 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006171 break;
6172 }
6173 }
6174
6175 if (rc >= HTTP_ERR_SIZE) {
6176 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
6177 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02006178 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006179 free(err);
6180 }
6181 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006182 else if (!strcmp(args[0], "compression")) {
6183 struct comp *comp;
6184 if (curproxy->comp == NULL) {
6185 comp = calloc(1, sizeof(struct comp));
6186 curproxy->comp = comp;
6187 } else {
6188 comp = curproxy->comp;
6189 }
6190
6191 if (!strcmp(args[1], "algo")) {
6192 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006193 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006194
William Lallemand82fe75c2012-10-23 10:25:10 +02006195 cur_arg = 2;
6196 if (!*args[cur_arg]) {
6197 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6198 file, linenum, args[0]);
6199 err_code |= ERR_ALERT | ERR_FATAL;
6200 goto out;
6201 }
6202 while (*(args[cur_arg])) {
6203 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6204 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6205 file, linenum, args[0], args[cur_arg]);
6206 err_code |= ERR_ALERT | ERR_FATAL;
6207 goto out;
6208 }
William Lallemand552df672012-11-07 13:21:47 +01006209 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6210 curproxy->comp->algos->end(&ctx);
6211 } else {
6212 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6213 file, linenum, args[0], args[cur_arg]);
6214 err_code |= ERR_ALERT | ERR_FATAL;
6215 goto out;
6216 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006217 cur_arg ++;
6218 continue;
6219 }
6220 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006221 else if (!strcmp(args[1], "offload")) {
6222 comp->offload = 1;
6223 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006224 else if (!strcmp(args[1], "type")) {
6225 int cur_arg;
6226 cur_arg = 2;
6227 if (!*args[cur_arg]) {
6228 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6229 file, linenum, args[0]);
6230 err_code |= ERR_ALERT | ERR_FATAL;
6231 goto out;
6232 }
6233 while (*(args[cur_arg])) {
6234 comp_append_type(comp, args[cur_arg]);
6235 cur_arg ++;
6236 continue;
6237 }
6238 }
6239 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006240 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006241 file, linenum, args[0]);
6242 err_code |= ERR_ALERT | ERR_FATAL;
6243 goto out;
6244 }
6245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006246 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006247 struct cfg_kw_list *kwl;
6248 int index;
6249
6250 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6251 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6252 if (kwl->kw[index].section != CFG_LISTEN)
6253 continue;
6254 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6255 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006256 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006257 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006258 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006259 err_code |= ERR_ALERT | ERR_FATAL;
6260 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006261 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006262 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006263 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006264 err_code |= ERR_WARN;
6265 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006266 }
Willy Tarreau93893792009-07-23 13:19:11 +02006267 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006268 }
6269 }
6270 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006271
Willy Tarreau6daf3432008-01-22 16:44:08 +01006272 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006273 err_code |= ERR_ALERT | ERR_FATAL;
6274 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006275 }
Willy Tarreau93893792009-07-23 13:19:11 +02006276 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006277 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006278 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006279}
6280
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006281int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006282cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6283{
6284#ifdef CONFIG_HAP_NS
6285 const char *err;
6286 const char *item = args[0];
6287
6288 if (!strcmp(item, "namespace_list")) {
6289 return 0;
6290 }
6291 else if (!strcmp(item, "namespace")) {
6292 size_t idx = 1;
6293 const char *current;
6294 while (*(current = args[idx++])) {
6295 err = invalid_char(current);
6296 if (err) {
6297 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6298 file, linenum, *err, item, current);
6299 return ERR_ALERT | ERR_FATAL;
6300 }
6301
6302 if (netns_store_lookup(current, strlen(current))) {
6303 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6304 file, linenum, current);
6305 return ERR_ALERT | ERR_FATAL;
6306 }
6307 if (!netns_store_insert(current)) {
6308 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6309 file, linenum, current);
6310 return ERR_ALERT | ERR_FATAL;
6311 }
6312 }
6313 }
6314
6315 return 0;
6316#else
6317 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6318 file, linenum);
6319 return ERR_ALERT | ERR_FATAL;
6320#endif
6321}
6322
6323int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006324cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6325{
6326
6327 int err_code = 0;
6328 const char *err;
6329
6330 if (!strcmp(args[0], "userlist")) { /* new userlist */
6331 struct userlist *newul;
6332
6333 if (!*args[1]) {
6334 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6335 file, linenum, args[0]);
6336 err_code |= ERR_ALERT | ERR_FATAL;
6337 goto out;
6338 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006339 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6340 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006341
6342 err = invalid_char(args[1]);
6343 if (err) {
6344 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6345 file, linenum, *err, args[0], args[1]);
6346 err_code |= ERR_ALERT | ERR_FATAL;
6347 goto out;
6348 }
6349
6350 for (newul = userlist; newul; newul = newul->next)
6351 if (!strcmp(newul->name, args[1])) {
6352 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6353 file, linenum, args[1]);
6354 err_code |= ERR_WARN;
6355 goto out;
6356 }
6357
6358 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6359 if (!newul) {
6360 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6361 err_code |= ERR_ALERT | ERR_ABORT;
6362 goto out;
6363 }
6364
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006365 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006366 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006367 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6368 err_code |= ERR_ALERT | ERR_ABORT;
6369 goto out;
6370 }
6371
6372 newul->next = userlist;
6373 userlist = newul;
6374
6375 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006376 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006377 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006378 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006379
6380 if (!*args[1]) {
6381 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6382 file, linenum, args[0]);
6383 err_code |= ERR_ALERT | ERR_FATAL;
6384 goto out;
6385 }
6386
6387 err = invalid_char(args[1]);
6388 if (err) {
6389 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6390 file, linenum, *err, args[0], args[1]);
6391 err_code |= ERR_ALERT | ERR_FATAL;
6392 goto out;
6393 }
6394
William Lallemand4ac9f542015-05-28 18:03:51 +02006395 if (!userlist)
6396 goto out;
6397
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006398 for (ag = userlist->groups; ag; ag = ag->next)
6399 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006400 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6401 file, linenum, args[1], userlist->name);
6402 err_code |= ERR_ALERT;
6403 goto out;
6404 }
6405
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006406 ag = calloc(1, sizeof(*ag));
6407 if (!ag) {
6408 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6409 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006410 goto out;
6411 }
6412
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006413 ag->name = strdup(args[1]);
6414 if (!ag) {
6415 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6416 err_code |= ERR_ALERT | ERR_ABORT;
6417 goto out;
6418 }
6419
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006420 cur_arg = 2;
6421
6422 while (*args[cur_arg]) {
6423 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006424 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006425 cur_arg += 2;
6426 continue;
6427 } else {
6428 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6429 file, linenum, args[0]);
6430 err_code |= ERR_ALERT | ERR_FATAL;
6431 goto out;
6432 }
6433 }
6434
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006435 ag->next = userlist->groups;
6436 userlist->groups = ag;
6437
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006438 } else if (!strcmp(args[0], "user")) { /* new user */
6439 struct auth_users *newuser;
6440 int cur_arg;
6441
6442 if (!*args[1]) {
6443 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6444 file, linenum, args[0]);
6445 err_code |= ERR_ALERT | ERR_FATAL;
6446 goto out;
6447 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006448 if (!userlist)
6449 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006450
6451 for (newuser = userlist->users; newuser; newuser = newuser->next)
6452 if (!strcmp(newuser->user, args[1])) {
6453 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6454 file, linenum, args[1], userlist->name);
6455 err_code |= ERR_ALERT;
6456 goto out;
6457 }
6458
6459 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6460 if (!newuser) {
6461 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6462 err_code |= ERR_ALERT | ERR_ABORT;
6463 goto out;
6464 }
6465
6466 newuser->user = strdup(args[1]);
6467
6468 newuser->next = userlist->users;
6469 userlist->users = newuser;
6470
6471 cur_arg = 2;
6472
6473 while (*args[cur_arg]) {
6474 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006475#ifdef CONFIG_HAP_CRYPT
6476 if (!crypt("", args[cur_arg + 1])) {
6477 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6478 file, linenum, newuser->user);
6479 err_code |= ERR_ALERT | ERR_FATAL;
6480 goto out;
6481 }
6482#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006483 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6484 file, linenum);
6485 err_code |= ERR_ALERT;
6486#endif
6487 newuser->pass = strdup(args[cur_arg + 1]);
6488 cur_arg += 2;
6489 continue;
6490 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6491 newuser->pass = strdup(args[cur_arg + 1]);
6492 newuser->flags |= AU_O_INSECURE;
6493 cur_arg += 2;
6494 continue;
6495 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006496 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006497 cur_arg += 2;
6498 continue;
6499 } else {
6500 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6501 file, linenum, args[0]);
6502 err_code |= ERR_ALERT | ERR_FATAL;
6503 goto out;
6504 }
6505 }
6506 } else {
6507 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6508 err_code |= ERR_ALERT | ERR_FATAL;
6509 }
6510
6511out:
6512 return err_code;
6513}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006514
6515/*
6516 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006517 * Returns the error code, 0 if OK, or any combination of :
6518 * - ERR_ABORT: must abort ASAP
6519 * - ERR_FATAL: we can continue parsing but not start the service
6520 * - ERR_WARN: a warning has been emitted
6521 * - ERR_ALERT: an alert has been emitted
6522 * Only the two first ones can stop processing, the two others are just
6523 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006524 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006525int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006526{
William Lallemand64e84512015-05-12 14:25:37 +02006527 char *thisline;
6528 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006529 FILE *f;
6530 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006531 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006532 struct cfg_section *cs = NULL;
6533 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006534 int readbytes = 0;
6535
6536 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006537 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006538 return -1;
6539 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006540
6541 /* Register internal sections */
6542 if (!cfg_register_section("listen", cfg_parse_listen) ||
6543 !cfg_register_section("frontend", cfg_parse_listen) ||
6544 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006545 !cfg_register_section("defaults", cfg_parse_listen) ||
6546 !cfg_register_section("global", cfg_parse_global) ||
6547 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006548 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006549 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006550 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006551 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006552
Willy Tarreaubaaee002006-06-26 02:48:02 +02006553 if ((f=fopen(file,"r")) == NULL)
6554 return -1;
6555
William Lallemandb2f07452015-05-12 14:27:13 +02006556next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006557 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006558 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006559 char *end;
6560 char *args[MAX_LINE_ARGS + 1];
6561 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006562 int dquote = 0; /* double quote */
6563 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006564
Willy Tarreaubaaee002006-06-26 02:48:02 +02006565 linenum++;
6566
6567 end = line + strlen(line);
6568
William Lallemand64e84512015-05-12 14:25:37 +02006569 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006570 /* Check if we reached the limit and the last char is not \n.
6571 * Watch out for the last line without the terminating '\n'!
6572 */
William Lallemand64e84512015-05-12 14:25:37 +02006573 char *newline;
6574 int newlinesize = linesize * 2;
6575
6576 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6577 if (newline == NULL) {
6578 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6579 file, linenum);
6580 err_code |= ERR_ALERT | ERR_FATAL;
6581 continue;
6582 }
6583
6584 readbytes = linesize - 1;
6585 linesize = newlinesize;
6586 thisline = newline;
6587 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006588 }
6589
William Lallemand64e84512015-05-12 14:25:37 +02006590 readbytes = 0;
6591
Willy Tarreaubaaee002006-06-26 02:48:02 +02006592 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006593 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006594 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006595
Willy Tarreaubaaee002006-06-26 02:48:02 +02006596 arg = 0;
6597 args[arg] = line;
6598
6599 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006600 if (*line == '"' && !squote) { /* double quote outside single quotes */
6601 if (dquote)
6602 dquote = 0;
6603 else
6604 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006605 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006606 end--;
6607 }
6608 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6609 if (squote)
6610 squote = 0;
6611 else
6612 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006613 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006614 end--;
6615 }
6616 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006617 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6618 * C equivalent value. Other combinations left unchanged (eg: \1).
6619 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006620 int skip = 0;
6621 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6622 *line = line[1];
6623 skip = 1;
6624 }
6625 else if (line[1] == 'r') {
6626 *line = '\r';
6627 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006629 else if (line[1] == 'n') {
6630 *line = '\n';
6631 skip = 1;
6632 }
6633 else if (line[1] == 't') {
6634 *line = '\t';
6635 skip = 1;
6636 }
6637 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006638 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006639 unsigned char hex1, hex2;
6640 hex1 = toupper(line[2]) - '0';
6641 hex2 = toupper(line[3]) - '0';
6642 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6643 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6644 *line = (hex1<<4) + hex2;
6645 skip = 3;
6646 }
6647 else {
6648 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006649 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006650 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006651 } else if (line[1] == '"') {
6652 *line = '"';
6653 skip = 1;
6654 } else if (line[1] == '\'') {
6655 *line = '\'';
6656 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006657 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6658 *line = '$';
6659 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006660 }
6661 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006662 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006663 end -= skip;
6664 }
6665 line++;
6666 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006667 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006668 /* end of string, end of loop */
6669 *line = 0;
6670 break;
6671 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006672 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006673 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006674 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006675 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006676 line++;
6677 args[++arg] = line;
6678 }
William Lallemandb2f07452015-05-12 14:27:13 +02006679 else if (dquote && *line == '$') {
6680 /* environment variables are evaluated inside double quotes */
6681 char *var_beg;
6682 char *var_end;
6683 char save_char;
6684 char *value;
6685 int val_len;
6686 int newlinesize;
6687 int braces = 0;
6688
6689 var_beg = line + 1;
6690 var_end = var_beg;
6691
6692 if (*var_beg == '{') {
6693 var_beg++;
6694 var_end++;
6695 braces = 1;
6696 }
6697
6698 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6699 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6700 err_code |= ERR_ALERT | ERR_FATAL;
6701 goto next_line; /* skip current line */
6702 }
6703
6704 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6705 var_end++;
6706
6707 save_char = *var_end;
6708 *var_end = '\0';
6709 value = getenv(var_beg);
6710 *var_end = save_char;
6711 val_len = value ? strlen(value) : 0;
6712
6713 if (braces) {
6714 if (*var_end == '}') {
6715 var_end++;
6716 braces = 0;
6717 } else {
6718 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
6719 err_code |= ERR_ALERT | ERR_FATAL;
6720 goto next_line; /* skip current line */
6721 }
6722 }
6723
6724 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
6725
6726 /* if not enough space in thisline */
6727 if (newlinesize > linesize) {
6728 char *newline;
6729
6730 newline = realloc(thisline, newlinesize * sizeof(*thisline));
6731 if (newline == NULL) {
6732 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
6733 err_code |= ERR_ALERT | ERR_FATAL;
6734 goto next_line; /* slip current line */
6735 }
6736 /* recompute pointers if realloc returns a new pointer */
6737 if (newline != thisline) {
6738 int i;
6739 int diff;
6740
6741 for (i = 0; i <= arg; i++) {
6742 diff = args[i] - thisline;
6743 args[i] = newline + diff;
6744 }
6745
6746 diff = var_end - thisline;
6747 var_end = newline + diff;
6748 diff = end - thisline;
6749 end = newline + diff;
6750 diff = line - thisline;
6751 line = newline + diff;
6752 thisline = newline;
6753 }
6754 linesize = newlinesize;
6755 }
6756
6757 /* insert value inside the line */
6758 memmove(line + val_len, var_end, end - var_end + 1);
6759 memcpy(line, value, val_len);
6760 end += val_len - (var_end - line);
6761 line += val_len;
6762 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006763 else {
6764 line++;
6765 }
6766 }
William Lallemandb2f07452015-05-12 14:27:13 +02006767
William Lallemandf9873ba2015-05-05 17:37:14 +02006768 if (dquote) {
6769 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
6770 err_code |= ERR_ALERT | ERR_FATAL;
6771 }
6772
6773 if (squote) {
6774 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
6775 err_code |= ERR_ALERT | ERR_FATAL;
6776 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006777
6778 /* empty line */
6779 if (!**args)
6780 continue;
6781
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006782 if (*line) {
6783 /* we had to stop due to too many args.
6784 * Let's terminate the string, print the offending part then cut the
6785 * last arg.
6786 */
6787 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6788 line++;
6789 *line = '\0';
6790
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006791 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006792 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006793 err_code |= ERR_ALERT | ERR_FATAL;
6794 args[arg] = line;
6795 }
6796
Willy Tarreau540abe42007-05-02 20:50:16 +02006797 /* zero out remaining args and ensure that at least one entry
6798 * is zeroed out.
6799 */
6800 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006801 args[arg] = line;
6802 }
6803
Willy Tarreau3842f002009-06-14 11:39:52 +02006804 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006805 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006806 char *tmp;
6807
Willy Tarreau3842f002009-06-14 11:39:52 +02006808 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006809 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006810 for (arg=0; *args[arg+1]; arg++)
6811 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006812 *tmp = '\0'; // fix the next arg to \0
6813 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006814 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006815 else if (!strcmp(args[0], "default")) {
6816 kwm = KWM_DEF;
6817 for (arg=0; *args[arg+1]; arg++)
6818 args[arg] = args[arg+1]; // shift args after inversion
6819 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006820
William Lallemand0f99e342011-10-12 17:50:54 +02006821 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6822 strcmp(args[0], "log") != 0) {
6823 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006824 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006825 }
6826
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006827 /* detect section start */
6828 list_for_each_entry(ics, &sections, list) {
6829 if (strcmp(args[0], ics->section_name) == 0) {
6830 cursection = ics->section_name;
6831 cs = ics;
6832 break;
6833 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006834 }
6835
Willy Tarreaubaaee002006-06-26 02:48:02 +02006836 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006837 if (cs)
6838 err_code |= cs->section_parser(file, linenum, args, kwm);
6839 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006840 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006841 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006842 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006843
6844 if (err_code & ERR_ABORT)
6845 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006846 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006847 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02006848 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006849 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006850 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006851}
6852
Willy Tarreau64ab6072014-09-16 12:17:36 +02006853/* This function propagates processes from frontend <from> to backend <to> so
6854 * that it is always guaranteed that a backend pointed to by a frontend is
6855 * bound to all of its processes. After that, if the target is a "listen"
6856 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02006857 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02006858 * checked first to ensure that <to> is already bound to all processes of
6859 * <from>, there is no risk of looping and we ensure to follow the shortest
6860 * path to the destination.
6861 *
6862 * It is possible to set <to> to NULL for the first call so that the function
6863 * takes care of visiting the initial frontend in <from>.
6864 *
6865 * It is important to note that the function relies on the fact that all names
6866 * have already been resolved.
6867 */
6868void propagate_processes(struct proxy *from, struct proxy *to)
6869{
6870 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006871
6872 if (to) {
6873 /* check whether we need to go down */
6874 if (from->bind_proc &&
6875 (from->bind_proc & to->bind_proc) == from->bind_proc)
6876 return;
6877
6878 if (!from->bind_proc && !to->bind_proc)
6879 return;
6880
6881 to->bind_proc = from->bind_proc ?
6882 (to->bind_proc | from->bind_proc) : 0;
6883
6884 /* now propagate down */
6885 from = to;
6886 }
6887
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006888 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006889 return;
6890
Willy Tarreauf6b70012014-12-18 14:00:43 +01006891 if (from->state == PR_STSTOPPED)
6892 return;
6893
Willy Tarreau64ab6072014-09-16 12:17:36 +02006894 /* default_backend */
6895 if (from->defbe.be)
6896 propagate_processes(from, from->defbe.be);
6897
6898 /* use_backend */
6899 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006900 if (rule->dynamic)
6901 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006902 to = rule->be.backend;
6903 propagate_processes(from, to);
6904 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02006905}
6906
Willy Tarreaubb925012009-07-23 13:36:36 +02006907/*
6908 * Returns the error code, 0 if OK, or any combination of :
6909 * - ERR_ABORT: must abort ASAP
6910 * - ERR_FATAL: we can continue parsing but not start the service
6911 * - ERR_WARN: a warning has been emitted
6912 * - ERR_ALERT: an alert has been emitted
6913 * Only the two first ones can stop processing, the two others are just
6914 * indicators.
6915 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006916int check_config_validity()
6917{
6918 int cfgerr = 0;
6919 struct proxy *curproxy = NULL;
6920 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006921 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006922 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006923 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006924
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006925 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006926 /*
6927 * Now, check for the integrity of all that we have collected.
6928 */
6929
6930 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006931 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006932
Willy Tarreau193b8c62012-11-22 00:17:38 +01006933 if (!global.tune.max_http_hdr)
6934 global.tune.max_http_hdr = MAX_HTTP_HDR;
6935
6936 if (!global.tune.cookie_len)
6937 global.tune.cookie_len = CAPTURE_LEN;
6938
6939 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6940
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006941 /* Post initialisation of the users and groups lists. */
6942 err_code = userlist_postinit();
6943 if (err_code != ERR_NONE)
6944 goto out;
6945
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006946 /* first, we will invert the proxy list order */
6947 curproxy = NULL;
6948 while (proxy) {
6949 struct proxy *next;
6950
6951 next = proxy->next;
6952 proxy->next = curproxy;
6953 curproxy = proxy;
6954 if (!next)
6955 break;
6956 proxy = next;
6957 }
6958
Willy Tarreau419ead82014-09-16 13:41:21 +02006959 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006960 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006961 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006962 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006963 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006964 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006965 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006966 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006967
Willy Tarreau050536d2012-10-04 08:47:34 +02006968 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006969 /* proxy ID not set, use automatic numbering with first
6970 * spare entry starting with next_pxid.
6971 */
6972 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6973 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6974 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006975 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006976 next_pxid++;
6977
Willy Tarreau55ea7572007-06-17 19:56:27 +02006978
Willy Tarreaubaaee002006-06-26 02:48:02 +02006979 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006980 /* ensure we don't keep listeners uselessly bound */
6981 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02006982 free((void *)curproxy->table.peers.name);
6983 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006984 continue;
6985 }
6986
Willy Tarreau102df612014-05-07 23:56:38 +02006987 /* Check multi-process mode compatibility for the current proxy */
6988
6989 if (curproxy->bind_proc) {
6990 /* an explicit bind-process was specified, let's check how many
6991 * processes remain.
6992 */
6993 nbproc = popcount(curproxy->bind_proc);
6994
6995 curproxy->bind_proc &= nbits(global.nbproc);
6996 if (!curproxy->bind_proc && nbproc == 1) {
6997 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);
6998 curproxy->bind_proc = 1;
6999 }
7000 else if (!curproxy->bind_proc && nbproc > 1) {
7001 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);
7002 curproxy->bind_proc = 0;
7003 }
7004 }
7005
Willy Tarreau3d209582014-05-09 17:06:11 +02007006 /* check and reduce the bind-proc of each listener */
7007 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7008 unsigned long mask;
7009
7010 if (!bind_conf->bind_proc)
7011 continue;
7012
7013 mask = nbits(global.nbproc);
7014 if (curproxy->bind_proc)
7015 mask &= curproxy->bind_proc;
7016 /* mask cannot be null here thanks to the previous checks */
7017
7018 nbproc = popcount(bind_conf->bind_proc);
7019 bind_conf->bind_proc &= mask;
7020
7021 if (!bind_conf->bind_proc && nbproc == 1) {
7022 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",
7023 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7024 bind_conf->bind_proc = mask & ~(mask - 1);
7025 }
7026 else if (!bind_conf->bind_proc && nbproc > 1) {
7027 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",
7028 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7029 bind_conf->bind_proc = 0;
7030 }
7031 }
7032
Willy Tarreauff01a212009-03-15 13:46:16 +01007033 switch (curproxy->mode) {
7034 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007035 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007036 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007037 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7038 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007039 cfgerr++;
7040 }
7041
7042 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007043 Warning("config : servers will be ignored for %s '%s'.\n",
7044 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007045 break;
7046
7047 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007048 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007049 break;
7050
7051 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007052 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007053 break;
7054 }
7055
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007056 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007057 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007058 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007059 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7060 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007061 cfgerr++;
7062 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007063#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007064 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007065 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7066 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007067 cfgerr++;
7068 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007069#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007070 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007071 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7072 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007073 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007074 }
7075 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007076 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007077 /* If no LB algo is set in a backend, and we're not in
7078 * transparent mode, dispatch mode nor proxy mode, we
7079 * want to use balance roundrobin by default.
7080 */
7081 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7082 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007083 }
7084 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007085
Willy Tarreau1620ec32011-08-06 17:05:02 +02007086 if (curproxy->options & PR_O_DISPATCH)
7087 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7088 else if (curproxy->options & PR_O_HTTP_PROXY)
7089 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7090 else if (curproxy->options & PR_O_TRANSP)
7091 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007092
Willy Tarreau1620ec32011-08-06 17:05:02 +02007093 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7094 if (curproxy->options & PR_O_DISABLE404) {
7095 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7096 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7097 err_code |= ERR_WARN;
7098 curproxy->options &= ~PR_O_DISABLE404;
7099 }
7100 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7101 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7102 "send-state", proxy_type_str(curproxy), curproxy->id);
7103 err_code |= ERR_WARN;
7104 curproxy->options &= ~PR_O2_CHK_SNDST;
7105 }
Willy Tarreauef781042010-01-27 11:53:01 +01007106 }
7107
Simon Horman98637e52014-06-20 12:30:16 +09007108 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7109 if (!global.external_check) {
7110 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7111 curproxy->id, "option external-check");
7112 cfgerr++;
7113 }
7114 if (!curproxy->check_command) {
7115 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7116 curproxy->id, "option external-check");
7117 cfgerr++;
7118 }
7119 }
7120
Simon Horman64e34162015-02-06 11:11:57 +09007121 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007122 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7123 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09007124 "'email-alert from', 'email-alert level' 'email-alert mailer', "
7125 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007126 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
7127 "to be present).\n",
7128 proxy_type_str(curproxy), curproxy->id);
7129 err_code |= ERR_WARN;
7130 free_email_alert(curproxy);
7131 }
7132 if (!curproxy->email_alert.myhostname)
7133 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09007134 }
7135
Simon Horman98637e52014-06-20 12:30:16 +09007136 if (curproxy->check_command) {
7137 int clear = 0;
7138 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7139 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7140 "external-check command", proxy_type_str(curproxy), curproxy->id);
7141 err_code |= ERR_WARN;
7142 clear = 1;
7143 }
7144 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
7145 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
7146 curproxy->id, "external-check command");
7147 cfgerr++;
7148 }
7149 if (clear) {
7150 free(curproxy->check_command);
7151 curproxy->check_command = NULL;
7152 }
7153 }
7154
7155 if (curproxy->check_path) {
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 path", proxy_type_str(curproxy), curproxy->id);
7159 err_code |= ERR_WARN;
7160 free(curproxy->check_path);
7161 curproxy->check_path = NULL;
7162 }
7163 }
7164
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007165 /* if a default backend was specified, let's find it */
7166 if (curproxy->defbe.name) {
7167 struct proxy *target;
7168
Willy Tarreauafb39922015-05-26 12:04:09 +02007169 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007170 if (!target) {
7171 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7172 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007173 cfgerr++;
7174 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007175 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7176 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007177 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007178 } else if (target->mode != curproxy->mode &&
7179 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7180
7181 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7182 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7183 curproxy->conf.file, curproxy->conf.line,
7184 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7185 target->conf.file, target->conf.line);
7186 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007187 } else {
7188 free(curproxy->defbe.name);
7189 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007190
7191 /* Emit a warning if this proxy also has some servers */
7192 if (curproxy->srv) {
7193 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7194 curproxy->id);
7195 err_code |= ERR_WARN;
7196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007197 }
7198 }
7199
Willy Tarreau55ea7572007-06-17 19:56:27 +02007200 /* find the target proxy for 'use_backend' rules */
7201 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007202 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007203 struct logformat_node *node;
7204 char *pxname;
7205
7206 /* Try to parse the string as a log format expression. If the result
7207 * of the parsing is only one entry containing a simple string, then
7208 * it's a standard string corresponding to a static rule, thus the
7209 * parsing is cancelled and be.name is restored to be resolved.
7210 */
7211 pxname = rule->be.name;
7212 LIST_INIT(&rule->be.expr);
7213 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7214 curproxy->conf.args.file, curproxy->conf.args.line);
7215 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7216
7217 if (!LIST_ISEMPTY(&rule->be.expr)) {
7218 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7219 rule->dynamic = 1;
7220 free(pxname);
7221 continue;
7222 }
7223 /* simple string: free the expression and fall back to static rule */
7224 free(node->arg);
7225 free(node);
7226 }
7227
7228 rule->dynamic = 0;
7229 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007230
Willy Tarreauafb39922015-05-26 12:04:09 +02007231 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007232 if (!target) {
7233 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7234 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007235 cfgerr++;
7236 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007237 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7238 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007239 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007240 } else if (target->mode != curproxy->mode &&
7241 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7242
7243 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7244 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7245 curproxy->conf.file, curproxy->conf.line,
7246 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7247 target->conf.file, target->conf.line);
7248 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007249 } else {
7250 free((void *)rule->be.name);
7251 rule->be.backend = target;
7252 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007253 }
7254
Willy Tarreau64ab6072014-09-16 12:17:36 +02007255 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007256 list_for_each_entry(srule, &curproxy->server_rules, list) {
7257 struct server *target = findserver(curproxy, srule->srv.name);
7258
7259 if (!target) {
7260 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7261 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7262 cfgerr++;
7263 continue;
7264 }
7265 free((void *)srule->srv.name);
7266 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007267 }
7268
Emeric Brunb982a3d2010-01-04 15:45:53 +01007269 /* find the target table for 'stick' rules */
7270 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7271 struct proxy *target;
7272
Emeric Brun1d33b292010-01-04 15:47:17 +01007273 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7274 if (mrule->flags & STK_IS_STORE)
7275 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7276
Emeric Brunb982a3d2010-01-04 15:45:53 +01007277 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007278 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007279 else
7280 target = curproxy;
7281
7282 if (!target) {
7283 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7284 curproxy->id, mrule->table.name);
7285 cfgerr++;
7286 }
7287 else if (target->table.size == 0) {
7288 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7289 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7290 cfgerr++;
7291 }
Willy Tarreau12785782012-04-27 21:37:17 +02007292 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7293 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007294 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7295 cfgerr++;
7296 }
7297 else {
7298 free((void *)mrule->table.name);
7299 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007300 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007301 }
7302 }
7303
7304 /* find the target table for 'store response' rules */
7305 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7306 struct proxy *target;
7307
Emeric Brun1d33b292010-01-04 15:47:17 +01007308 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7309
Emeric Brunb982a3d2010-01-04 15:45:53 +01007310 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007311 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007312 else
7313 target = curproxy;
7314
7315 if (!target) {
7316 Alert("Proxy '%s': unable to find store table '%s'.\n",
7317 curproxy->id, mrule->table.name);
7318 cfgerr++;
7319 }
7320 else if (target->table.size == 0) {
7321 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7322 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7323 cfgerr++;
7324 }
Willy Tarreau12785782012-04-27 21:37:17 +02007325 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7326 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007327 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7328 cfgerr++;
7329 }
7330 else {
7331 free((void *)mrule->table.name);
7332 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007333 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007334 }
7335 }
7336
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007337 /* find the target table for 'tcp-request' layer 4 rules */
7338 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7339 struct proxy *target;
7340
Willy Tarreaub4c84932013-07-23 19:15:30 +02007341 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007342 continue;
7343
7344 if (trule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007345 target = proxy_tbl_by_name(trule->act_prm.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007346 else
7347 target = curproxy;
7348
7349 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007350 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7351 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007352 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007353 cfgerr++;
7354 }
7355 else if (target->table.size == 0) {
7356 Alert("Proxy '%s': table '%s' used but not configured.\n",
7357 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7358 cfgerr++;
7359 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007360 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7361 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7362 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 +01007363 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007364 cfgerr++;
7365 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007366 else {
7367 free(trule->act_prm.trk_ctr.table.n);
7368 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007369 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007370 * to pass a list of counters to track and allocate them right here using
7371 * stktable_alloc_data_type().
7372 */
7373 }
7374 }
7375
Willy Tarreaud1f96522010-08-03 19:34:32 +02007376 /* find the target table for 'tcp-request' layer 6 rules */
7377 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7378 struct proxy *target;
7379
Willy Tarreaub4c84932013-07-23 19:15:30 +02007380 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007381 continue;
7382
7383 if (trule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007384 target = proxy_tbl_by_name(trule->act_prm.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007385 else
7386 target = curproxy;
7387
7388 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007389 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7390 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007391 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007392 cfgerr++;
7393 }
7394 else if (target->table.size == 0) {
7395 Alert("Proxy '%s': table '%s' used but not configured.\n",
7396 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7397 cfgerr++;
7398 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007399 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7400 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7401 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 +01007402 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007403 cfgerr++;
7404 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007405 else {
7406 free(trule->act_prm.trk_ctr.table.n);
7407 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007408 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007409 * to pass a list of counters to track and allocate them right here using
7410 * stktable_alloc_data_type().
7411 */
7412 }
7413 }
7414
Willy Tarreau09448f72014-06-25 18:12:15 +02007415 /* find the target table for 'http-request' layer 7 rules */
7416 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7417 struct proxy *target;
7418
7419 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
7420 continue;
7421
7422 if (hrqrule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007423 target = proxy_tbl_by_name(hrqrule->act_prm.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007424 else
7425 target = curproxy;
7426
7427 if (!target) {
7428 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7429 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
7430 http_req_trk_idx(hrqrule->action));
7431 cfgerr++;
7432 }
7433 else if (target->table.size == 0) {
7434 Alert("Proxy '%s': table '%s' used but not configured.\n",
7435 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
7436 cfgerr++;
7437 }
7438 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
7439 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7440 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
7441 http_req_trk_idx(hrqrule->action));
7442 cfgerr++;
7443 }
7444 else {
7445 free(hrqrule->act_prm.trk_ctr.table.n);
7446 hrqrule->act_prm.trk_ctr.table.t = &target->table;
7447 /* Note: if we decide to enhance the track-sc syntax, we may be able
7448 * to pass a list of counters to track and allocate them right here using
7449 * stktable_alloc_data_type().
7450 */
7451 }
7452 }
7453
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007454 /* move any "block" rules at the beginning of the http-request rules */
7455 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7456 /* insert block_rules into http_req_rules at the beginning */
7457 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7458 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7459 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7460 curproxy->http_req_rules.n = curproxy->block_rules.n;
7461 LIST_INIT(&curproxy->block_rules);
7462 }
7463
Emeric Brun32da3c42010-09-23 18:39:19 +02007464 if (curproxy->table.peers.name) {
7465 struct peers *curpeers = peers;
7466
7467 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7468 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7469 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007470 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007471 break;
7472 }
7473 }
7474
7475 if (!curpeers) {
7476 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7477 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007478 free((void *)curproxy->table.peers.name);
7479 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007480 cfgerr++;
7481 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007482 else if (curpeers->state == PR_STSTOPPED) {
7483 /* silently disable this peers section */
7484 curproxy->table.peers.p = NULL;
7485 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007486 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007487 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7488 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007489 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007490 cfgerr++;
7491 }
7492 }
7493
Simon Horman9dc49962015-01-30 11:22:59 +09007494
7495 if (curproxy->email_alert.mailers.name) {
7496 struct mailers *curmailers = mailers;
7497
7498 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7499 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7500 free(curproxy->email_alert.mailers.name);
7501 curproxy->email_alert.mailers.m = curmailers;
7502 curmailers->users++;
7503 break;
7504 }
7505 }
7506
7507 if (!curmailers) {
7508 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7509 curproxy->id, curproxy->email_alert.mailers.name);
7510 free_email_alert(curproxy);
7511 cfgerr++;
7512 }
7513 }
7514
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007515 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007516 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007517 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7518 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7519 "proxy", curproxy->id);
7520 cfgerr++;
7521 goto out_uri_auth_compat;
7522 }
7523
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007524 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007525 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007526 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007527 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007528
Willy Tarreau95fa4692010-02-01 13:05:50 +01007529 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7530 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007531
7532 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007533 uri_auth_compat_req[i++] = "realm";
7534 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7535 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007536
Willy Tarreau95fa4692010-02-01 13:05:50 +01007537 uri_auth_compat_req[i++] = "unless";
7538 uri_auth_compat_req[i++] = "{";
7539 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7540 uri_auth_compat_req[i++] = "}";
7541 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007542
Willy Tarreauff011f22011-01-06 17:51:27 +01007543 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7544 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007545 cfgerr++;
7546 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007547 }
7548
Willy Tarreauff011f22011-01-06 17:51:27 +01007549 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007550
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007551 if (curproxy->uri_auth->auth_realm) {
7552 free(curproxy->uri_auth->auth_realm);
7553 curproxy->uri_auth->auth_realm = NULL;
7554 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007555
7556 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007557 }
7558out_uri_auth_compat:
7559
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007560 /* compile the log format */
7561 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007562 if (curproxy->conf.logformat_string != default_http_log_format &&
7563 curproxy->conf.logformat_string != default_tcp_log_format &&
7564 curproxy->conf.logformat_string != clf_http_log_format)
7565 free(curproxy->conf.logformat_string);
7566 curproxy->conf.logformat_string = NULL;
7567 free(curproxy->conf.lfs_file);
7568 curproxy->conf.lfs_file = NULL;
7569 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007570 }
7571
Willy Tarreau62a61232013-04-12 18:13:46 +02007572 if (curproxy->conf.logformat_string) {
7573 curproxy->conf.args.ctx = ARGC_LOG;
7574 curproxy->conf.args.file = curproxy->conf.lfs_file;
7575 curproxy->conf.args.line = curproxy->conf.lfs_line;
7576 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007577 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007578 curproxy->conf.args.file = NULL;
7579 curproxy->conf.args.line = 0;
7580 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007581
Willy Tarreau62a61232013-04-12 18:13:46 +02007582 if (curproxy->conf.uniqueid_format_string) {
7583 curproxy->conf.args.ctx = ARGC_UIF;
7584 curproxy->conf.args.file = curproxy->conf.uif_file;
7585 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007586 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007587 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007588 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007589 curproxy->conf.args.file = NULL;
7590 curproxy->conf.args.line = 0;
7591 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007592
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007593 /* only now we can check if some args remain unresolved.
7594 * This must be done after the users and groups resolution.
7595 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007596 cfgerr += smp_resolve_args(curproxy);
7597 if (!cfgerr)
7598 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007599
Willy Tarreau2738a142006-07-08 17:28:09 +02007600 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007601 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007602 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007603 (!curproxy->timeout.connect ||
7604 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007605 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007606 " | While not properly invalid, you will certainly encounter various problems\n"
7607 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007608 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007609 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007610 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007611 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007612
Willy Tarreau1fa31262007-12-03 00:36:16 +01007613 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7614 * We must still support older configurations, so let's find out whether those
7615 * parameters have been set or must be copied from contimeouts.
7616 */
7617 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007618 if (!curproxy->timeout.tarpit ||
7619 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007620 /* tarpit timeout not set. We search in the following order:
7621 * default.tarpit, curr.connect, default.connect.
7622 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007623 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007624 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007625 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007626 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007627 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007628 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007629 }
7630 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007631 (!curproxy->timeout.queue ||
7632 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007633 /* queue timeout not set. We search in the following order:
7634 * default.queue, curr.connect, default.connect.
7635 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007636 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007637 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007638 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007639 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007640 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007641 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007642 }
7643 }
7644
Willy Tarreau1620ec32011-08-06 17:05:02 +02007645 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007646 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7647 curproxy->check_req = (char *)malloc(curproxy->check_len);
7648 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007649 }
7650
Willy Tarreau215663d2014-06-13 18:30:23 +02007651 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7652 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7653 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7654 proxy_type_str(curproxy), curproxy->id);
7655 err_code |= ERR_WARN;
7656 }
7657
Willy Tarreau193b8c62012-11-22 00:17:38 +01007658 /* ensure that cookie capture length is not too large */
7659 if (curproxy->capture_len >= global.tune.cookie_len) {
7660 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7661 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7662 err_code |= ERR_WARN;
7663 curproxy->capture_len = global.tune.cookie_len - 1;
7664 }
7665
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007666 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007667 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007668 curproxy->req_cap_pool = create_pool("ptrcap",
7669 curproxy->nb_req_cap * sizeof(char *),
7670 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007671 }
7672
7673 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007674 curproxy->rsp_cap_pool = create_pool("ptrcap",
7675 curproxy->nb_rsp_cap * sizeof(char *),
7676 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007677 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007678
Willy Tarreaubaaee002006-06-26 02:48:02 +02007679 /* first, we will invert the servers list order */
7680 newsrv = NULL;
7681 while (curproxy->srv) {
7682 struct server *next;
7683
7684 next = curproxy->srv->next;
7685 curproxy->srv->next = newsrv;
7686 newsrv = curproxy->srv;
7687 if (!next)
7688 break;
7689 curproxy->srv = next;
7690 }
7691
Willy Tarreau17edc812014-01-03 12:14:34 +01007692 /* Check that no server name conflicts. This causes trouble in the stats.
7693 * We only emit a warning for the first conflict affecting each server,
7694 * in order to avoid combinatory explosion if all servers have the same
7695 * name. We do that only for servers which do not have an explicit ID,
7696 * because these IDs were made also for distinguishing them and we don't
7697 * want to annoy people who correctly manage them.
7698 */
7699 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7700 struct server *other_srv;
7701
7702 if (newsrv->puid)
7703 continue;
7704
7705 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7706 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7707 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7708 newsrv->conf.file, newsrv->conf.line,
7709 proxy_type_str(curproxy), curproxy->id,
7710 newsrv->id, other_srv->conf.line);
7711 break;
7712 }
7713 }
7714 }
7715
Willy Tarreaudd701652010-05-25 23:03:02 +02007716 /* assign automatic UIDs to servers which don't have one yet */
7717 next_id = 1;
7718 newsrv = curproxy->srv;
7719 while (newsrv != NULL) {
7720 if (!newsrv->puid) {
7721 /* server ID not set, use automatic numbering with first
7722 * spare entry starting with next_svid.
7723 */
7724 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7725 newsrv->conf.id.key = newsrv->puid = next_id;
7726 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7727 }
7728 next_id++;
7729 newsrv = newsrv->next;
7730 }
7731
Willy Tarreau20697042007-11-15 23:26:18 +01007732 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007733 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007734
Willy Tarreau62c3be22012-01-20 13:12:32 +01007735 /*
7736 * If this server supports a maxconn parameter, it needs a dedicated
7737 * tasks to fill the emptied slots when a connection leaves.
7738 * Also, resolve deferred tracking dependency if needed.
7739 */
7740 newsrv = curproxy->srv;
7741 while (newsrv != NULL) {
7742 if (newsrv->minconn > newsrv->maxconn) {
7743 /* Only 'minconn' was specified, or it was higher than or equal
7744 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7745 * this will avoid further useless expensive computations.
7746 */
7747 newsrv->maxconn = newsrv->minconn;
7748 } else if (newsrv->maxconn && !newsrv->minconn) {
7749 /* minconn was not specified, so we set it to maxconn */
7750 newsrv->minconn = newsrv->maxconn;
7751 }
7752
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007753#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007754 if (newsrv->use_ssl || newsrv->check.use_ssl)
7755 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007756#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007757
Willy Tarreau2f075e92013-12-03 11:11:34 +01007758 /* set the check type on the server */
7759 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7760
Willy Tarreau62c3be22012-01-20 13:12:32 +01007761 if (newsrv->trackit) {
7762 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007763 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007764 char *pname, *sname;
7765
7766 pname = newsrv->trackit;
7767 sname = strrchr(pname, '/');
7768
7769 if (sname)
7770 *sname++ = '\0';
7771 else {
7772 sname = pname;
7773 pname = NULL;
7774 }
7775
7776 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007777 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007778 if (!px) {
7779 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7780 proxy_type_str(curproxy), curproxy->id,
7781 newsrv->id, pname);
7782 cfgerr++;
7783 goto next_srv;
7784 }
7785 } else
7786 px = curproxy;
7787
7788 srv = findserver(px, sname);
7789 if (!srv) {
7790 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7791 proxy_type_str(curproxy), curproxy->id,
7792 newsrv->id, sname);
7793 cfgerr++;
7794 goto next_srv;
7795 }
7796
Willy Tarreau32091232014-05-16 13:52:00 +02007797 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7798 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7799 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007800 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007801 "tracking as it does not have any check nor agent enabled.\n",
7802 proxy_type_str(curproxy), curproxy->id,
7803 newsrv->id, px->id, srv->id);
7804 cfgerr++;
7805 goto next_srv;
7806 }
7807
7808 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7809
7810 if (loop) {
7811 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7812 "belongs to a tracking chain looping back to %s/%s.\n",
7813 proxy_type_str(curproxy), curproxy->id,
7814 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007815 cfgerr++;
7816 goto next_srv;
7817 }
7818
7819 if (curproxy != px &&
7820 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7821 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7822 "tracking: disable-on-404 option inconsistency.\n",
7823 proxy_type_str(curproxy), curproxy->id,
7824 newsrv->id, px->id, srv->id);
7825 cfgerr++;
7826 goto next_srv;
7827 }
7828
7829 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007830 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007831 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007832 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007833 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007834 }
7835
7836 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007837 newsrv->tracknext = srv->trackers;
7838 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007839
7840 free(newsrv->trackit);
7841 newsrv->trackit = NULL;
7842 }
7843 next_srv:
7844 newsrv = newsrv->next;
7845 }
7846
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007847 /* We have to initialize the server lookup mechanism depending
7848 * on what LB algorithm was choosen.
7849 */
7850
7851 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7852 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7853 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007854 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7855 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7856 init_server_map(curproxy);
7857 } else {
7858 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7859 fwrr_init_server_groups(curproxy);
7860 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007861 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007862
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007863 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007864 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7865 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7866 fwlc_init_server_tree(curproxy);
7867 } else {
7868 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7869 fas_init_server_tree(curproxy);
7870 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007871 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007872
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007873 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007874 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7875 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7876 chash_init_server_tree(curproxy);
7877 } else {
7878 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7879 init_server_map(curproxy);
7880 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007881 break;
7882 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007883
7884 if (curproxy->options & PR_O_LOGASAP)
7885 curproxy->to_log &= ~LW_BYTES;
7886
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007887 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007888 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007889 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7890 proxy_type_str(curproxy), curproxy->id);
7891 err_code |= ERR_WARN;
7892 }
7893
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007894 if (curproxy->mode != PR_MODE_HTTP) {
7895 int optnum;
7896
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007897 if (curproxy->uri_auth) {
7898 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7899 proxy_type_str(curproxy), curproxy->id);
7900 err_code |= ERR_WARN;
7901 curproxy->uri_auth = NULL;
7902 }
7903
Willy Tarreau87cf5142011-08-19 22:57:24 +02007904 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007905 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7906 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7907 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007908 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007909 }
7910
7911 if (curproxy->options & PR_O_ORGTO) {
7912 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7913 "originalto", proxy_type_str(curproxy), curproxy->id);
7914 err_code |= ERR_WARN;
7915 curproxy->options &= ~PR_O_ORGTO;
7916 }
7917
7918 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7919 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7920 (curproxy->cap & cfg_opts[optnum].cap) &&
7921 (curproxy->options & cfg_opts[optnum].val)) {
7922 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7923 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7924 err_code |= ERR_WARN;
7925 curproxy->options &= ~cfg_opts[optnum].val;
7926 }
7927 }
7928
7929 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7930 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7931 (curproxy->cap & cfg_opts2[optnum].cap) &&
7932 (curproxy->options2 & cfg_opts2[optnum].val)) {
7933 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7934 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7935 err_code |= ERR_WARN;
7936 curproxy->options2 &= ~cfg_opts2[optnum].val;
7937 }
7938 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007939
Pieter Baauwd551fb52013-05-08 22:49:23 +02007940#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007941 if (curproxy->conn_src.bind_hdr_occ) {
7942 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007943 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007944 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007945 err_code |= ERR_WARN;
7946 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007947#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007948 }
7949
Willy Tarreaubaaee002006-06-26 02:48:02 +02007950 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007951 * ensure that we're not cross-dressing a TCP server into HTTP.
7952 */
7953 newsrv = curproxy->srv;
7954 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007955 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007956 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7957 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007958 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007959 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007960
Willy Tarreau0cec3312011-10-31 13:49:26 +01007961 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7962 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7963 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7964 err_code |= ERR_WARN;
7965 }
7966
Willy Tarreauc93cd162014-05-13 15:54:22 +02007967 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007968 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7969 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7970 err_code |= ERR_WARN;
7971 }
7972
Pieter Baauwd551fb52013-05-08 22:49:23 +02007973#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007974 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7975 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007976 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 +01007977 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007978 err_code |= ERR_WARN;
7979 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007980#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007981 newsrv = newsrv->next;
7982 }
7983
Willy Tarreaue42bd962014-09-16 16:21:19 +02007984 /* check if we have a frontend with "tcp-request content" looking at L7
7985 * with no inspect-delay
7986 */
7987 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7988 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7989 if (trule->action == TCP_ACT_CAPTURE &&
7990 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7991 break;
7992 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7993 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7994 break;
7995 }
7996
7997 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7998 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7999 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8000 " This means that these rules will randomly find their contents. This can be fixed by"
8001 " setting the tcp-request inspect-delay.\n",
8002 proxy_type_str(curproxy), curproxy->id);
8003 err_code |= ERR_WARN;
8004 }
8005 }
8006
Willy Tarreauc1a21672009-08-16 22:37:44 +02008007 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008008 if (!curproxy->accept)
8009 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008010
Willy Tarreauc1a21672009-08-16 22:37:44 +02008011 if (curproxy->tcp_req.inspect_delay ||
8012 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008013 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008014
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008015 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008016 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008017 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008018 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008019
8020 /* both TCP and HTTP must check switching rules */
8021 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
8022 }
8023
8024 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008025 if (curproxy->tcp_req.inspect_delay ||
8026 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8027 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8028
Emeric Brun97679e72010-09-23 17:56:44 +02008029 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8030 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8031
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008032 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008033 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008034 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008035 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008036
8037 /* If the backend does requires RDP cookie persistence, we have to
8038 * enable the corresponding analyser.
8039 */
8040 if (curproxy->options2 & PR_O2_RDPC_PRST)
8041 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
8042 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008043 }
8044
8045 /***********************************************************/
8046 /* At this point, target names have already been resolved. */
8047 /***********************************************************/
8048
8049 /* Check multi-process mode compatibility */
8050
8051 if (global.nbproc > 1 && global.stats_fe) {
8052 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8053 unsigned long mask;
8054
8055 mask = nbits(global.nbproc);
8056 if (global.stats_fe->bind_proc)
8057 mask &= global.stats_fe->bind_proc;
8058
8059 if (bind_conf->bind_proc)
8060 mask &= bind_conf->bind_proc;
8061
8062 /* stop here if more than one process is used */
8063 if (popcount(mask) > 1)
8064 break;
8065 }
8066 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8067 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");
8068 }
8069 }
8070
8071 /* Make each frontend inherit bind-process from its listeners when not specified. */
8072 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8073 if (curproxy->bind_proc)
8074 continue;
8075
8076 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8077 unsigned long mask;
8078
Willy Tarreaue428b082015-05-04 21:57:58 +02008079 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008080 curproxy->bind_proc |= mask;
8081 }
8082
8083 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008084 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008085 }
8086
8087 if (global.stats_fe) {
8088 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8089 unsigned long mask;
8090
Willy Tarreaue428b082015-05-04 21:57:58 +02008091 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008092 global.stats_fe->bind_proc |= mask;
8093 }
8094 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008095 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008096 }
8097
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008098 /* propagate bindings from frontends to backends. Don't do it if there
8099 * are any fatal errors as we must not call it with unresolved proxies.
8100 */
8101 if (!cfgerr) {
8102 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8103 if (curproxy->cap & PR_CAP_FE)
8104 propagate_processes(curproxy, NULL);
8105 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008106 }
8107
8108 /* Bind each unbound backend to all processes when not specified. */
8109 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8110 if (curproxy->bind_proc)
8111 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008112 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008113 }
8114
8115 /*******************************************************/
8116 /* At this step, all proxies have a non-null bind_proc */
8117 /*******************************************************/
8118
8119 /* perform the final checks before creating tasks */
8120
8121 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8122 struct listener *listener;
8123 unsigned int next_id;
8124 int nbproc;
8125
8126 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008127
Emeric Brunc52962f2012-11-15 18:28:02 +01008128#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008129 /* Configure SSL for each bind line.
8130 * Note: if configuration fails at some point, the ->ctx member
8131 * remains NULL so that listeners can later detach.
8132 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008133 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008134 int alloc_ctx;
8135
Emeric Brunc52962f2012-11-15 18:28:02 +01008136 if (!bind_conf->is_ssl) {
8137 if (bind_conf->default_ctx) {
8138 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8139 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8140 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008141 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008142 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008143 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008144 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008145 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008146 cfgerr++;
8147 continue;
8148 }
8149
Emeric Brun8dc60392014-05-09 13:52:00 +02008150 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008151 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008152 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8153 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");
8154 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008155 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008156 cfgerr++;
8157 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008158 }
8159
Emeric Brunfc0421f2012-09-07 17:30:07 +02008160 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008161 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008162 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008163#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008164
Willy Tarreaue6b98942007-10-29 01:09:36 +01008165 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008166 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008167 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008168 if (!listener->luid) {
8169 /* listener ID not set, use automatic numbering with first
8170 * spare entry starting with next_luid.
8171 */
8172 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8173 listener->conf.id.key = listener->luid = next_id;
8174 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008175 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008176 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008177
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008178 /* enable separate counters */
8179 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8180 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008181 if (!listener->name)
8182 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008183 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008184
Willy Tarreaue6b98942007-10-29 01:09:36 +01008185 if (curproxy->options & PR_O_TCP_NOLING)
8186 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008187 if (!listener->maxconn)
8188 listener->maxconn = curproxy->maxconn;
8189 if (!listener->backlog)
8190 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008191 if (!listener->maxaccept)
8192 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8193
8194 /* we want to have an optimal behaviour on single process mode to
8195 * maximize the work at once, but in multi-process we want to keep
8196 * some fairness between processes, so we target half of the max
8197 * number of events to be balanced over all the processes the proxy
8198 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8199 * used to disable the limit.
8200 */
8201 if (listener->maxaccept > 0) {
8202 if (nbproc > 1)
8203 listener->maxaccept = (listener->maxaccept + 1) / 2;
8204 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8205 }
8206
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008207 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008208 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008209 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008210 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008211
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008212 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8213 listener->options |= LI_O_TCP_RULES;
8214
Willy Tarreaude3041d2010-05-31 10:56:17 +02008215 if (curproxy->mon_mask.s_addr)
8216 listener->options |= LI_O_CHK_MONNET;
8217
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008218 /* smart accept mode is automatic in HTTP mode */
8219 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008220 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008221 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8222 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008223 }
8224
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008225 /* Release unused SSL configs */
8226 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8227 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008228 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008229#ifdef USE_OPENSSL
8230 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008231 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008232 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008233 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008234 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008235 if(bind_conf->keys_ref) {
8236 free(bind_conf->keys_ref->filename);
8237 free(bind_conf->keys_ref->tlskeys);
8238 free(bind_conf->keys_ref);
8239 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008240#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008241 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008242
Willy Tarreau102df612014-05-07 23:56:38 +02008243 if (nbproc > 1) {
8244 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008245 int count, maxproc = 0;
8246
8247 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8248 count = popcount(bind_conf->bind_proc);
8249 if (count > maxproc)
8250 maxproc = count;
8251 }
8252 /* backends have 0, frontends have 1 or more */
8253 if (maxproc != 1)
8254 Warning("Proxy '%s': in multi-process mode, stats will be"
8255 " limited to process assigned to the current request.\n",
8256 curproxy->id);
8257
Willy Tarreau102df612014-05-07 23:56:38 +02008258 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8259 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8260 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008261 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008262 }
Willy Tarreau102df612014-05-07 23:56:38 +02008263 if (curproxy->appsession_name) {
8264 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
8265 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008266 }
Willy Tarreau102df612014-05-07 23:56:38 +02008267 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8268 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8269 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008270 }
8271 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008272
8273 /* create the task associated with the proxy */
8274 curproxy->task = task_new();
8275 if (curproxy->task) {
8276 curproxy->task->context = curproxy;
8277 curproxy->task->process = manage_proxy;
8278 /* no need to queue, it will be done automatically if some
8279 * listener gets limited.
8280 */
8281 curproxy->task->expire = TICK_ETERNITY;
8282 } else {
8283 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8284 curproxy->id);
8285 cfgerr++;
8286 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008287 }
8288
Willy Tarreaufbb78422011-06-05 15:38:35 +02008289 /* automatically compute fullconn if not set. We must not do it in the
8290 * loop above because cross-references are not yet fully resolved.
8291 */
8292 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8293 /* If <fullconn> is not set, let's set it to 10% of the sum of
8294 * the possible incoming frontend's maxconns.
8295 */
8296 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8297 struct proxy *fe;
8298 int total = 0;
8299
8300 /* sum up the number of maxconns of frontends which
8301 * reference this backend at least once or which are
8302 * the same one ('listen').
8303 */
8304 for (fe = proxy; fe; fe = fe->next) {
8305 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008306 int found = 0;
8307
8308 if (!(fe->cap & PR_CAP_FE))
8309 continue;
8310
8311 if (fe == curproxy) /* we're on a "listen" instance */
8312 found = 1;
8313
8314 if (fe->defbe.be == curproxy) /* "default_backend" */
8315 found = 1;
8316
8317 /* check if a "use_backend" rule matches */
8318 if (!found) {
8319 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008320 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008321 found = 1;
8322 break;
8323 }
8324 }
8325 }
8326
Willy Tarreaufbb78422011-06-05 15:38:35 +02008327 /* now we've checked all possible ways to reference a backend
8328 * from a frontend.
8329 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008330 if (!found)
8331 continue;
8332 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008333 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008334 /* we have the sum of the maxconns in <total>. We only
8335 * keep 10% of that sum to set the default fullconn, with
8336 * a hard minimum of 1 (to avoid a divide by zero).
8337 */
8338 curproxy->fullconn = (total + 9) / 10;
8339 if (!curproxy->fullconn)
8340 curproxy->fullconn = 1;
8341 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008342 }
8343
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008344 /*
8345 * Recount currently required checks.
8346 */
8347
8348 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8349 int optnum;
8350
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008351 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8352 if (curproxy->options & cfg_opts[optnum].val)
8353 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008354
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008355 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8356 if (curproxy->options2 & cfg_opts2[optnum].val)
8357 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008358 }
8359
Willy Tarreau0fca4832015-05-01 19:12:05 +02008360 /* compute the required process bindings for the peers */
8361 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8362 if (curproxy->table.peers.p)
8363 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8364
Willy Tarreau122541c2011-09-07 21:24:49 +02008365 if (peers) {
8366 struct peers *curpeers = peers, **last;
8367 struct peer *p, *pb;
8368
Willy Tarreau1e273012015-05-01 19:15:17 +02008369 /* Remove all peers sections which don't have a valid listener,
8370 * which are not used by any table, or which are bound to more
8371 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008372 */
8373 last = &peers;
8374 while (*last) {
8375 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008376
8377 if (curpeers->state == PR_STSTOPPED) {
8378 /* the "disabled" keyword was present */
8379 if (curpeers->peers_fe)
8380 stop_proxy(curpeers->peers_fe);
8381 curpeers->peers_fe = NULL;
8382 }
8383 else if (!curpeers->peers_fe) {
8384 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8385 curpeers->id, localpeer);
8386 }
Willy Tarreau1e273012015-05-01 19:15:17 +02008387 else if (popcount(curpeers->peers_fe->bind_proc) != 1) {
8388 /* either it's totally stopped or too much used */
8389 if (curpeers->peers_fe->bind_proc) {
8390 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008391 "running in different processes (%d different ones). "
8392 "Check global.nbproc and all tables' bind-process "
8393 "settings.\n", curpeers->id, popcount(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008394 cfgerr++;
8395 }
8396 stop_proxy(curpeers->peers_fe);
8397 curpeers->peers_fe = NULL;
8398 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008399 else {
Willy Tarreau122541c2011-09-07 21:24:49 +02008400 last = &curpeers->next;
8401 continue;
8402 }
8403
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008404 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008405 p = curpeers->remote;
8406 while (p) {
8407 pb = p->next;
8408 free(p->id);
8409 free(p);
8410 p = pb;
8411 }
8412
8413 /* Destroy and unlink this curpeers section.
8414 * Note: curpeers is backed up into *last.
8415 */
8416 free(curpeers->id);
8417 curpeers = curpeers->next;
8418 free(*last);
8419 *last = curpeers;
8420 }
8421 }
8422
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008423 /* initialize stick-tables on backend capable proxies. This must not
8424 * be done earlier because the data size may be discovered while parsing
8425 * other proxies.
8426 */
8427 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8428 if (curproxy->state == PR_STSTOPPED)
8429 continue;
8430
8431 if (!stktable_init(&curproxy->table)) {
8432 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8433 cfgerr++;
8434 }
8435 }
8436
Simon Horman0d16a402015-01-30 11:22:58 +09008437 if (mailers) {
8438 struct mailers *curmailers = mailers, **last;
8439 struct mailer *m, *mb;
8440
8441 /* Remove all mailers sections which don't have a valid listener.
8442 * This can happen when a mailers section is never referenced.
8443 */
8444 last = &mailers;
8445 while (*last) {
8446 curmailers = *last;
8447 if (curmailers->users) {
8448 last = &curmailers->next;
8449 continue;
8450 }
8451
8452 Warning("Removing incomplete section 'mailers %s'.\n",
8453 curmailers->id);
8454
8455 m = curmailers->mailer_list;
8456 while (m) {
8457 mb = m->next;
8458 free(m->id);
8459 free(m);
8460 m = mb;
8461 }
8462
8463 /* Destroy and unlink this curmailers section.
8464 * Note: curmailers is backed up into *last.
8465 */
8466 free(curmailers->id);
8467 curmailers = curmailers->next;
8468 free(*last);
8469 *last = curmailers;
8470 }
8471 }
8472
Willy Tarreau34eb6712011-10-24 18:15:04 +02008473 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008474 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008475 MEM_F_SHARED);
8476
Willy Tarreaubb925012009-07-23 13:36:36 +02008477 if (cfgerr > 0)
8478 err_code |= ERR_ALERT | ERR_FATAL;
8479 out:
8480 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008481}
8482
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008483/*
8484 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8485 * parsing sessions.
8486 */
8487void cfg_register_keywords(struct cfg_kw_list *kwl)
8488{
8489 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8490}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008491
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008492/*
8493 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8494 */
8495void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8496{
8497 LIST_DEL(&kwl->list);
8498 LIST_INIT(&kwl->list);
8499}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008500
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008501/* this function register new section in the haproxy configuration file.
8502 * <section_name> is the name of this new section and <section_parser>
8503 * is the called parser. If two section declaration have the same name,
8504 * only the first declared is used.
8505 */
8506int cfg_register_section(char *section_name,
8507 int (*section_parser)(const char *, int, char **, int))
8508{
8509 struct cfg_section *cs;
8510
8511 cs = calloc(1, sizeof(*cs));
8512 if (!cs) {
8513 Alert("register section '%s': out of memory.\n", section_name);
8514 return 0;
8515 }
8516
8517 cs->section_name = section_name;
8518 cs->section_parser = section_parser;
8519
8520 LIST_ADDQ(&sections, &cs->list);
8521
8522 return 1;
8523}
8524
Willy Tarreaubaaee002006-06-26 02:48:02 +02008525/*
8526 * Local variables:
8527 * c-indent-level: 8
8528 * c-basic-offset: 8
8529 * End:
8530 */