blob: 778edf74c0e0da5957cd7b90402441b68d42a94c [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010049#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020050#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090051#include <types/mailers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020052
Willy Tarreaueb0c6142007-05-07 00:53:22 +020053#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010054#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020056#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020058#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020059#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020060#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020061#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020062#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010063#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020064#include <proto/lb_fwlc.h>
65#include <proto/lb_fwrr.h>
66#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020067#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020069#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010070#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020071#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010072#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010073#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020074#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020075#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020076#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020077#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020078#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020079#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020080#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010081#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020082
Emeric Brunfc0421f2012-09-07 17:30:07 +020083#ifdef USE_OPENSSL
84#include <types/ssl_sock.h>
85#include <proto/ssl_sock.h>
86#include <proto/shctx.h>
87#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020088
Willy Tarreauf3c69202006-07-09 16:42:34 +020089/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
90 * ssl-hello-chk option to ensure that the remote server speaks SSL.
91 *
92 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
93 */
94const char sslv3_client_hello_pkt[] = {
95 "\x16" /* ContentType : 0x16 = Hanshake */
96 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
97 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
98 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
99 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
100 "\x03\x00" /* Hello Version : 0x0300 = v3 */
101 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
102 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
103 "\x00" /* Session ID length : empty (no session ID) */
104 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
105 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
106 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
107 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
108 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
109 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
110 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
111 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
112 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
113 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
114 "\x00\x38" "\x00\x39" "\x00\x3A"
115 "\x01" /* Compression Length : 0x01 = 1 byte for types */
116 "\x00" /* Compression Type : 0x00 = NULL compression */
117};
118
Willy Tarreau3842f002009-06-14 11:39:52 +0200119/* various keyword modifiers */
120enum kw_mod {
121 KWM_STD = 0, /* normal */
122 KWM_NO, /* "no" prefixed before the keyword */
123 KWM_DEF, /* "default" prefixed before the keyword */
124};
125
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100126/* permit to store configuration section */
127struct cfg_section {
128 struct list list;
129 char *section_name;
130 int (*section_parser)(const char *, int, char **, int);
131};
132
133/* Used to chain configuration sections definitions. This list
134 * stores struct cfg_section
135 */
136struct list sections = LIST_HEAD_INIT(sections);
137
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100139struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100140 const char *name;
141 unsigned int val;
142 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100143 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100145};
146
147/* proxy->options */
148static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100150 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
151 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
152 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
153 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
154 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
155 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200157 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200158 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100159 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
161 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
162 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100164#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100165 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100166#else
167 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100168#endif
169
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100171};
172
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173/* proxy->options2 */
174static const struct cfg_opt cfg_opts2[] =
175{
176#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100177 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
178 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
179 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100180#else
181 { "splice-request", 0, 0, 0, 0 },
182 { "splice-response", 0, 0, 0, 0 },
183 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100185 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
186 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
187 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
188 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
189 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
190 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
191 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
192 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
193 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400194 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100195 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200196 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200197 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100198 { NULL, 0, 0, 0 }
199};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200
Willy Tarreau6daf3432008-01-22 16:44:08 +0100201static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
203int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100204int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200206/* List head of all known configuration keywords */
207static struct cfg_kw_list cfg_keywords = {
208 .list = LIST_HEAD_INIT(cfg_keywords.list)
209};
210
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211/*
212 * converts <str> to a list of listeners which are dynamically allocated.
213 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
214 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
215 * - <port> is a numerical port from 1 to 65535 ;
216 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
217 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200218 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
219 * not NULL, it must be a valid pointer to either NULL or a freeable area that
220 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200222int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223{
224 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100225 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 int port, end;
227
228 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200229
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100231 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100232 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233
234 str = next;
235 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100236 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237 *next++ = 0;
238 }
239
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100240 ss2 = str2sa_range(str, &port, &end, err,
241 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
242 if (!ss2)
243 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100245 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100246 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200247 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100248 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200250
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100251 if (!port || !end) {
252 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
253 goto fail;
254 }
255
Emeric Bruned760922010-10-22 17:59:25 +0200256 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200257 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200258 goto fail;
259 }
260
261 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200262 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200263 goto fail;
264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100266 else if (ss2->ss_family == AF_UNSPEC) {
267 socklen_t addr_len;
268
269 /* We want to attach to an already bound fd whose number
270 * is in the addr part of ss2 when cast to sockaddr_in.
271 * Note that by definition there is a single listener.
272 * We still have to determine the address family to
273 * register the correct protocol.
274 */
275 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
276 addr_len = sizeof(*ss2);
277 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
278 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
279 goto fail;
280 }
281
282 port = end = get_host_port(ss2);
283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200284
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100285 /* OK the address looks correct */
286 ss = *ss2;
287
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288 for (; port <= end; port++) {
289 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100290 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200291 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
292 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
293 l->frontend = curproxy;
294 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295
Willy Tarreau40aa0702013-03-10 23:51:38 +0100296 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200298 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100299 l->state = LI_INIT;
300
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100301 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100303 tcpv4_add_listener(l);
304 }
Emeric Bruned760922010-10-22 17:59:25 +0200305 else if (ss.ss_family == AF_INET6) {
306 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
307 tcpv6_add_listener(l);
308 }
309 else {
Emeric Bruned760922010-10-22 17:59:25 +0200310 uxst_add_listener(l);
311 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200312
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200313 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100314 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315 } /* end for(port) */
316 } /* end while(next) */
317 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319 fail:
320 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200321 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200322}
323
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200324/* Report a warning if a rule is placed after a 'tcp-request content' rule.
325 * Return 1 if the warning has been emitted, otherwise 0.
326 */
327int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
328{
329 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
330 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
331 file, line, arg);
332 return 1;
333 }
334 return 0;
335}
336
Willy Tarreau61d18892009-03-31 10:49:21 +0200337/* Report a warning if a rule is placed after a 'block' rule.
338 * Return 1 if the warning has been emitted, otherwise 0.
339 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100340int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200341{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200342 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200343 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
344 file, line, arg);
345 return 1;
346 }
347 return 0;
348}
349
Willy Tarreau5002f572014-04-23 01:32:02 +0200350/* Report a warning if a rule is placed after an 'http_request' rule.
351 * Return 1 if the warning has been emitted, otherwise 0.
352 */
353int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
354{
355 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
356 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
357 file, line, arg);
358 return 1;
359 }
360 return 0;
361}
362
Willy Tarreau61d18892009-03-31 10:49:21 +0200363/* Report a warning if a rule is placed after a reqrewrite rule.
364 * Return 1 if the warning has been emitted, otherwise 0.
365 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100366int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200367{
368 if (proxy->req_exp) {
369 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
370 file, line, arg);
371 return 1;
372 }
373 return 0;
374}
375
376/* Report a warning if a rule is placed after a reqadd rule.
377 * Return 1 if the warning has been emitted, otherwise 0.
378 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100379int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200380{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100381 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200382 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
383 file, line, arg);
384 return 1;
385 }
386 return 0;
387}
388
389/* Report a warning if a rule is placed after a redirect rule.
390 * Return 1 if the warning has been emitted, otherwise 0.
391 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100392int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200393{
394 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
395 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
396 file, line, arg);
397 return 1;
398 }
399 return 0;
400}
401
402/* Report a warning if a rule is placed after a 'use_backend' rule.
403 * Return 1 if the warning has been emitted, otherwise 0.
404 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100405int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200406{
407 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
408 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
409 file, line, arg);
410 return 1;
411 }
412 return 0;
413}
414
Willy Tarreauee445d92014-04-23 01:39:04 +0200415/* Report a warning if a rule is placed after a 'use-server' rule.
416 * Return 1 if the warning has been emitted, otherwise 0.
417 */
418int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
419{
420 if (!LIST_ISEMPTY(&proxy->server_rules)) {
421 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
422 file, line, arg);
423 return 1;
424 }
425 return 0;
426}
427
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200428/* report a warning if a "tcp request connection" rule is dangerously placed */
429int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
430{
431 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
432 warnif_rule_after_block(proxy, file, line, arg) ||
433 warnif_rule_after_http_req(proxy, file, line, arg) ||
434 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
435 warnif_rule_after_reqadd(proxy, file, line, arg) ||
436 warnif_rule_after_redirect(proxy, file, line, arg) ||
437 warnif_rule_after_use_backend(proxy, file, line, arg) ||
438 warnif_rule_after_use_server(proxy, file, line, arg);
439}
440
441/* report a warning if a "tcp request content" rule is dangerously placed */
442int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
443{
444 return warnif_rule_after_block(proxy, file, line, arg) ||
445 warnif_rule_after_http_req(proxy, file, line, arg) ||
446 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
447 warnif_rule_after_reqadd(proxy, file, line, arg) ||
448 warnif_rule_after_redirect(proxy, file, line, arg) ||
449 warnif_rule_after_use_backend(proxy, file, line, arg) ||
450 warnif_rule_after_use_server(proxy, file, line, arg);
451}
452
Willy Tarreau61d18892009-03-31 10:49:21 +0200453/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100454int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200455{
Willy Tarreau5002f572014-04-23 01:32:02 +0200456 return warnif_rule_after_http_req(proxy, file, line, arg) ||
457 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
458 warnif_rule_after_reqadd(proxy, file, line, arg) ||
459 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200460 warnif_rule_after_use_backend(proxy, file, line, arg) ||
461 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200462}
463
464/* report a warning if an http-request rule is dangerously placed */
465int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
466{
Willy Tarreau61d18892009-03-31 10:49:21 +0200467 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
468 warnif_rule_after_reqadd(proxy, file, line, arg) ||
469 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200470 warnif_rule_after_use_backend(proxy, file, line, arg) ||
471 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200472}
473
474/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100475int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200476{
477 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
478 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200479 warnif_rule_after_use_backend(proxy, file, line, arg) ||
480 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200481}
482
483/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100484int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200485{
486 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200487 warnif_rule_after_use_backend(proxy, file, line, arg) ||
488 warnif_rule_after_use_server(proxy, file, line, arg);
489}
490
491/* report a warning if a redirect rule is dangerously placed */
492int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
493{
494 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
495 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200496}
497
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100498/* Report it if a request ACL condition uses some keywords that are incompatible
499 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
500 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
501 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100502 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100503static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100504{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100505 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200506 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100507
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100508 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100509 return 0;
510
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100511 acl = acl_cond_conflicts(cond, where);
512 if (acl) {
513 if (acl->name && *acl->name)
514 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
515 file, line, acl->name, sample_ckp_names(where));
516 else
517 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200518 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100519 return ERR_WARN;
520 }
521 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100522 return 0;
523
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100524 if (acl->name && *acl->name)
525 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200526 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100527 else
528 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200529 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100530 return ERR_WARN;
531}
532
Willy Tarreaubaaee002006-06-26 02:48:02 +0200533/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200534 * parse a line in a <global> section. Returns the error code, 0 if OK, or
535 * any combination of :
536 * - ERR_ABORT: must abort ASAP
537 * - ERR_FATAL: we can continue parsing but not start the service
538 * - ERR_WARN: a warning has been emitted
539 * - ERR_ALERT: an alert has been emitted
540 * Only the two first ones can stop processing, the two others are just
541 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200542 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200543int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200544{
Willy Tarreau058e9072009-07-20 09:30:05 +0200545 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200546 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200547
548 if (!strcmp(args[0], "global")) { /* new section */
549 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200551 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200552 else if (!strcmp(args[0], "ca-base")) {
553#ifdef USE_OPENSSL
554 if (global.ca_base != NULL) {
555 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
556 err_code |= ERR_ALERT;
557 goto out;
558 }
559 if (*(args[1]) == 0) {
560 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT | ERR_FATAL;
562 goto out;
563 }
564 global.ca_base = strdup(args[1]);
565#else
566 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
567 err_code |= ERR_ALERT | ERR_FATAL;
568 goto out;
569#endif
570 }
571 else if (!strcmp(args[0], "crt-base")) {
572#ifdef USE_OPENSSL
573 if (global.crt_base != NULL) {
574 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
575 err_code |= ERR_ALERT;
576 goto out;
577 }
578 if (*(args[1]) == 0) {
579 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
580 err_code |= ERR_ALERT | ERR_FATAL;
581 goto out;
582 }
583 global.crt_base = strdup(args[1]);
584#else
585 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
586 err_code |= ERR_ALERT | ERR_FATAL;
587 goto out;
588#endif
589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 else if (!strcmp(args[0], "daemon")) {
591 global.mode |= MODE_DAEMON;
592 }
593 else if (!strcmp(args[0], "debug")) {
594 global.mode |= MODE_DEBUG;
595 }
596 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100597 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200598 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200599 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100600 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200601 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100603 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200604 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100605 else if (!strcmp(args[0], "nosplice")) {
606 global.tune.options &= ~GTUNE_USE_SPLICE;
607 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200608 else if (!strcmp(args[0], "nogetaddrinfo")) {
609 global.tune.options &= ~GTUNE_USE_GAI;
610 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611 else if (!strcmp(args[0], "quiet")) {
612 global.mode |= MODE_QUIET;
613 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200614 else if (!strcmp(args[0], "tune.maxpollevents")) {
615 if (global.tune.maxpollevents != 0) {
616 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200617 err_code |= ERR_ALERT;
618 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200619 }
620 if (*(args[1]) == 0) {
621 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200622 err_code |= ERR_ALERT | ERR_FATAL;
623 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200624 }
625 global.tune.maxpollevents = atol(args[1]);
626 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100627 else if (!strcmp(args[0], "tune.maxaccept")) {
628 if (global.tune.maxaccept != 0) {
629 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200630 err_code |= ERR_ALERT;
631 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100632 }
633 if (*(args[1]) == 0) {
634 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200635 err_code |= ERR_ALERT | ERR_FATAL;
636 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100637 }
638 global.tune.maxaccept = atol(args[1]);
639 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200640 else if (!strcmp(args[0], "tune.chksize")) {
641 if (*(args[1]) == 0) {
642 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
643 err_code |= ERR_ALERT | ERR_FATAL;
644 goto out;
645 }
646 global.tune.chksize = atol(args[1]);
647 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200648#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200649 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
650 global.tune.sslprivatecache = 1;
651 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100652 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200653 if (*(args[1]) == 0) {
654 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
655 err_code |= ERR_ALERT | ERR_FATAL;
656 goto out;
657 }
658 global.tune.sslcachesize = atol(args[1]);
659 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100660 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
661 unsigned int ssllifetime;
662 const char *res;
663
664 if (*(args[1]) == 0) {
665 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
666 err_code |= ERR_ALERT | ERR_FATAL;
667 goto out;
668 }
669
670 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
671 if (res) {
672 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
673 file, linenum, *res, args[0]);
674 err_code |= ERR_ALERT | ERR_FATAL;
675 goto out;
676 }
677
678 global.tune.ssllifetime = ssllifetime;
679 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100680 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
681 if (*(args[1]) == 0) {
682 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
683 err_code |= ERR_ALERT | ERR_FATAL;
684 goto out;
685 }
686 global.tune.ssl_max_record = atol(args[1]);
687 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200688 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
689 if (*(args[1]) == 0) {
690 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
691 err_code |= ERR_ALERT | ERR_FATAL;
692 goto out;
693 }
694 global.tune.ssl_default_dh_param = atol(args[1]);
695 if (global.tune.ssl_default_dh_param < 1024) {
696 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
697 err_code |= ERR_ALERT | ERR_FATAL;
698 goto out;
699 }
700 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200701#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100702 else if (!strcmp(args[0], "tune.buffers.limit")) {
703 if (*(args[1]) == 0) {
704 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708 global.tune.buf_limit = atol(args[1]);
709 if (global.tune.buf_limit) {
710 if (global.tune.buf_limit < 3)
711 global.tune.buf_limit = 3;
712 if (global.tune.buf_limit <= global.tune.reserved_bufs)
713 global.tune.buf_limit = global.tune.reserved_bufs + 1;
714 }
715 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100716 else if (!strcmp(args[0], "tune.buffers.reserve")) {
717 if (*(args[1]) == 0) {
718 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
721 }
722 global.tune.reserved_bufs = atol(args[1]);
723 if (global.tune.reserved_bufs < 2)
724 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100725 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
726 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100727 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200728 else if (!strcmp(args[0], "tune.bufsize")) {
729 if (*(args[1]) == 0) {
730 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
731 err_code |= ERR_ALERT | ERR_FATAL;
732 goto out;
733 }
734 global.tune.bufsize = atol(args[1]);
735 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
736 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100737 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100738 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200739 }
740 else if (!strcmp(args[0], "tune.maxrewrite")) {
741 if (*(args[1]) == 0) {
742 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
743 err_code |= ERR_ALERT | ERR_FATAL;
744 goto out;
745 }
746 global.tune.maxrewrite = atol(args[1]);
747 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
748 global.tune.maxrewrite = global.tune.bufsize / 2;
749 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100750 else if (!strcmp(args[0], "tune.idletimer")) {
751 unsigned int idle;
752 const char *res;
753
754 if (*(args[1]) == 0) {
755 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
756 err_code |= ERR_ALERT | ERR_FATAL;
757 goto out;
758 }
759
760 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
761 if (res) {
762 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
763 file, linenum, *res, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
767
768 if (idle > 65535) {
769 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
772 }
773 global.tune.idle_timer = idle;
774 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100775 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
776 if (global.tune.client_rcvbuf != 0) {
777 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
778 err_code |= ERR_ALERT;
779 goto out;
780 }
781 if (*(args[1]) == 0) {
782 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
783 err_code |= ERR_ALERT | ERR_FATAL;
784 goto out;
785 }
786 global.tune.client_rcvbuf = atol(args[1]);
787 }
788 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
789 if (global.tune.server_rcvbuf != 0) {
790 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
791 err_code |= ERR_ALERT;
792 goto out;
793 }
794 if (*(args[1]) == 0) {
795 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
798 }
799 global.tune.server_rcvbuf = atol(args[1]);
800 }
801 else if (!strcmp(args[0], "tune.sndbuf.client")) {
802 if (global.tune.client_sndbuf != 0) {
803 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
804 err_code |= ERR_ALERT;
805 goto out;
806 }
807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
811 }
812 global.tune.client_sndbuf = atol(args[1]);
813 }
814 else if (!strcmp(args[0], "tune.sndbuf.server")) {
815 if (global.tune.server_sndbuf != 0) {
816 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
817 err_code |= ERR_ALERT;
818 goto out;
819 }
820 if (*(args[1]) == 0) {
821 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
822 err_code |= ERR_ALERT | ERR_FATAL;
823 goto out;
824 }
825 global.tune.server_sndbuf = atol(args[1]);
826 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200827 else if (!strcmp(args[0], "tune.pipesize")) {
828 if (*(args[1]) == 0) {
829 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
832 }
833 global.tune.pipesize = atol(args[1]);
834 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100835 else if (!strcmp(args[0], "tune.http.cookielen")) {
836 if (*(args[1]) == 0) {
837 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
838 err_code |= ERR_ALERT | ERR_FATAL;
839 goto out;
840 }
841 global.tune.cookie_len = atol(args[1]) + 1;
842 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200843 else if (!strcmp(args[0], "tune.http.maxhdr")) {
844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849 global.tune.max_http_hdr = atol(args[1]);
850 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100851 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
852#ifdef USE_ZLIB
853 if (*args[1]) {
854 global.tune.zlibmemlevel = atoi(args[1]);
855 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
856 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
857 file, linenum, args[0]);
858 err_code |= ERR_ALERT | ERR_FATAL;
859 goto out;
860 }
861 } else {
862 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
863 file, linenum, args[0]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867#else
868 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
869 err_code |= ERR_ALERT | ERR_FATAL;
870 goto out;
871#endif
872 }
873 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
874#ifdef USE_ZLIB
875 if (*args[1]) {
876 global.tune.zlibwindowsize = atoi(args[1]);
877 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
878 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
879 file, linenum, args[0]);
880 err_code |= ERR_ALERT | ERR_FATAL;
881 goto out;
882 }
883 } else {
884 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
885 file, linenum, args[0]);
886 err_code |= ERR_ALERT | ERR_FATAL;
887 goto out;
888 }
889#else
890 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
891 err_code |= ERR_ALERT | ERR_FATAL;
892 goto out;
893#endif
894 }
William Lallemandf3747832012-11-09 12:33:10 +0100895 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
896 if (*args[1]) {
897 global.tune.comp_maxlevel = atoi(args[1]);
898 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
899 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
900 file, linenum, args[0]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904 } else {
905 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
906 file, linenum, args[0]);
907 err_code |= ERR_ALERT | ERR_FATAL;
908 goto out;
909 }
910 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200911 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
912 if (*args[1]) {
913 global.tune.pattern_cache = atoi(args[1]);
914 if (global.tune.pattern_cache < 0) {
915 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
916 file, linenum, args[0]);
917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
919 }
920 } else {
921 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
922 file, linenum, args[0]);
923 err_code |= ERR_ALERT | ERR_FATAL;
924 goto out;
925 }
926 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 else if (!strcmp(args[0], "uid")) {
928 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200929 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200930 err_code |= ERR_ALERT;
931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 }
933 if (*(args[1]) == 0) {
934 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT | ERR_FATAL;
936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
938 global.uid = atol(args[1]);
939 }
940 else if (!strcmp(args[0], "gid")) {
941 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200942 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200943 err_code |= ERR_ALERT;
944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200945 }
946 if (*(args[1]) == 0) {
947 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200948 err_code |= ERR_ALERT | ERR_FATAL;
949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950 }
951 global.gid = atol(args[1]);
952 }
Simon Horman98637e52014-06-20 12:30:16 +0900953 else if (!strcmp(args[0], "external-check")) {
954 global.external_check = 1;
955 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200956 /* user/group name handling */
957 else if (!strcmp(args[0], "user")) {
958 struct passwd *ha_user;
959 if (global.uid != 0) {
960 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200961 err_code |= ERR_ALERT;
962 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200963 }
964 errno = 0;
965 ha_user = getpwnam(args[1]);
966 if (ha_user != NULL) {
967 global.uid = (int)ha_user->pw_uid;
968 }
969 else {
970 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200971 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200972 }
973 }
974 else if (!strcmp(args[0], "group")) {
975 struct group *ha_group;
976 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200977 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200978 err_code |= ERR_ALERT;
979 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200980 }
981 errno = 0;
982 ha_group = getgrnam(args[1]);
983 if (ha_group != NULL) {
984 global.gid = (int)ha_group->gr_gid;
985 }
986 else {
987 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200988 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200989 }
990 }
991 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200993 if (*(args[1]) == 0) {
994 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200995 err_code |= ERR_ALERT | ERR_FATAL;
996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997 }
998 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100999 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1000 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1001 file, linenum, args[0], LONGBITS, global.nbproc);
1002 err_code |= ERR_ALERT | ERR_FATAL;
1003 goto out;
1004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001005 }
1006 else if (!strcmp(args[0], "maxconn")) {
1007 if (global.maxconn != 0) {
1008 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001009 err_code |= ERR_ALERT;
1010 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001011 }
1012 if (*(args[1]) == 0) {
1013 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001014 err_code |= ERR_ALERT | ERR_FATAL;
1015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001016 }
1017 global.maxconn = atol(args[1]);
1018#ifdef SYSTEM_MAXCONN
1019 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1020 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
1021 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001022 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001023 }
1024#endif /* SYSTEM_MAXCONN */
1025 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001026 else if (!strcmp(args[0], "maxsslconn")) {
1027#ifdef USE_OPENSSL
1028 if (*(args[1]) == 0) {
1029 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1030 err_code |= ERR_ALERT | ERR_FATAL;
1031 goto out;
1032 }
1033 global.maxsslconn = atol(args[1]);
1034#else
Emeric Brun0914df82012-10-02 18:45:42 +02001035 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1036 err_code |= ERR_ALERT | ERR_FATAL;
1037 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001038#endif
1039 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001040 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1041#ifdef USE_OPENSSL
1042 if (*(args[1]) == 0) {
1043 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1044 err_code |= ERR_ALERT | ERR_FATAL;
1045 goto out;
1046 }
1047 free(global.listen_default_ciphers);
1048 global.listen_default_ciphers = strdup(args[1]);
1049#else
1050 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1051 err_code |= ERR_ALERT | ERR_FATAL;
1052 goto out;
1053#endif
1054 }
1055 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1056#ifdef USE_OPENSSL
1057 if (*(args[1]) == 0) {
1058 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1059 err_code |= ERR_ALERT | ERR_FATAL;
1060 goto out;
1061 }
1062 free(global.connect_default_ciphers);
1063 global.connect_default_ciphers = strdup(args[1]);
1064#else
1065 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1066 err_code |= ERR_ALERT | ERR_FATAL;
1067 goto out;
1068#endif
1069 }
Emeric Brun850efd52014-01-29 12:24:34 +01001070 else if (!strcmp(args[0], "ssl-server-verify")) {
1071 if (*(args[1]) == 0) {
1072 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1073 err_code |= ERR_ALERT | ERR_FATAL;
1074 goto out;
1075 }
1076 if (strcmp(args[1],"none") == 0)
1077 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1078 else if (strcmp(args[1],"required") == 0)
1079 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1080 else {
1081 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1082 err_code |= ERR_ALERT | ERR_FATAL;
1083 goto out;
1084 }
1085 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001086 else if (!strcmp(args[0], "maxconnrate")) {
1087 if (global.cps_lim != 0) {
1088 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1089 err_code |= ERR_ALERT;
1090 goto out;
1091 }
1092 if (*(args[1]) == 0) {
1093 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1094 err_code |= ERR_ALERT | ERR_FATAL;
1095 goto out;
1096 }
1097 global.cps_lim = atol(args[1]);
1098 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001099 else if (!strcmp(args[0], "maxsessrate")) {
1100 if (global.sps_lim != 0) {
1101 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1102 err_code |= ERR_ALERT;
1103 goto out;
1104 }
1105 if (*(args[1]) == 0) {
1106 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1107 err_code |= ERR_ALERT | ERR_FATAL;
1108 goto out;
1109 }
1110 global.sps_lim = atol(args[1]);
1111 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001112 else if (!strcmp(args[0], "maxsslrate")) {
1113 if (global.ssl_lim != 0) {
1114 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1115 err_code |= ERR_ALERT;
1116 goto out;
1117 }
1118 if (*(args[1]) == 0) {
1119 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1120 err_code |= ERR_ALERT | ERR_FATAL;
1121 goto out;
1122 }
1123 global.ssl_lim = atol(args[1]);
1124 }
William Lallemandd85f9172012-11-09 17:05:39 +01001125 else if (!strcmp(args[0], "maxcomprate")) {
1126 if (*(args[1]) == 0) {
1127 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1128 err_code |= ERR_ALERT | ERR_FATAL;
1129 goto out;
1130 }
1131 global.comp_rate_lim = atoi(args[1]) * 1024;
1132 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001133 else if (!strcmp(args[0], "maxpipes")) {
1134 if (global.maxpipes != 0) {
1135 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT;
1137 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001138 }
1139 if (*(args[1]) == 0) {
1140 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001141 err_code |= ERR_ALERT | ERR_FATAL;
1142 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001143 }
1144 global.maxpipes = atol(args[1]);
1145 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001146 else if (!strcmp(args[0], "maxzlibmem")) {
1147 if (*(args[1]) == 0) {
1148 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1149 err_code |= ERR_ALERT | ERR_FATAL;
1150 goto out;
1151 }
William Lallemande3a7d992012-11-20 11:25:20 +01001152 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001153 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001154 else if (!strcmp(args[0], "maxcompcpuusage")) {
1155 if (*(args[1]) == 0) {
1156 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1157 err_code |= ERR_ALERT | ERR_FATAL;
1158 goto out;
1159 }
1160 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001161 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001162 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1163 err_code |= ERR_ALERT | ERR_FATAL;
1164 goto out;
1165 }
1166}
1167
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 else if (!strcmp(args[0], "ulimit-n")) {
1169 if (global.rlimit_nofile != 0) {
1170 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001171 err_code |= ERR_ALERT;
1172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173 }
1174 if (*(args[1]) == 0) {
1175 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001176 err_code |= ERR_ALERT | ERR_FATAL;
1177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001178 }
1179 global.rlimit_nofile = atol(args[1]);
1180 }
1181 else if (!strcmp(args[0], "chroot")) {
1182 if (global.chroot != NULL) {
1183 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001184 err_code |= ERR_ALERT;
1185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001186 }
1187 if (*(args[1]) == 0) {
1188 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001189 err_code |= ERR_ALERT | ERR_FATAL;
1190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001191 }
1192 global.chroot = strdup(args[1]);
1193 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001194 else if (!strcmp(args[0], "description")) {
1195 int i, len=0;
1196 char *d;
1197
1198 if (!*args[1]) {
1199 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1200 file, linenum, args[0]);
1201 err_code |= ERR_ALERT | ERR_FATAL;
1202 goto out;
1203 }
1204
Willy Tarreau348acfe2014-04-14 15:00:39 +02001205 for (i = 1; *args[i]; i++)
1206 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001207
1208 if (global.desc)
1209 free(global.desc);
1210
1211 global.desc = d = (char *)calloc(1, len);
1212
Willy Tarreau348acfe2014-04-14 15:00:39 +02001213 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1214 for (i = 2; *args[i]; i++)
1215 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001216 }
1217 else if (!strcmp(args[0], "node")) {
1218 int i;
1219 char c;
1220
1221 for (i=0; args[1][i]; i++) {
1222 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001223 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1224 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001225 break;
1226 }
1227
1228 if (!i || args[1][i]) {
1229 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1230 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1231 file, linenum, args[0]);
1232 err_code |= ERR_ALERT | ERR_FATAL;
1233 goto out;
1234 }
1235
1236 if (global.node)
1237 free(global.node);
1238
1239 global.node = strdup(args[1]);
1240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001241 else if (!strcmp(args[0], "pidfile")) {
1242 if (global.pidfile != NULL) {
1243 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001244 err_code |= ERR_ALERT;
1245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001246 }
1247 if (*(args[1]) == 0) {
1248 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001251 }
1252 global.pidfile = strdup(args[1]);
1253 }
Emeric Bruned760922010-10-22 17:59:25 +02001254 else if (!strcmp(args[0], "unix-bind")) {
1255 int cur_arg = 1;
1256 while (*(args[cur_arg])) {
1257 if (!strcmp(args[cur_arg], "prefix")) {
1258 if (global.unix_bind.prefix != NULL) {
1259 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1260 err_code |= ERR_ALERT;
1261 cur_arg += 2;
1262 continue;
1263 }
1264
1265 if (*(args[cur_arg+1]) == 0) {
1266 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1267 err_code |= ERR_ALERT | ERR_FATAL;
1268 goto out;
1269 }
1270 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1271 cur_arg += 2;
1272 continue;
1273 }
1274
1275 if (!strcmp(args[cur_arg], "mode")) {
1276
1277 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1278 cur_arg += 2;
1279 continue;
1280 }
1281
1282 if (!strcmp(args[cur_arg], "uid")) {
1283
1284 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1285 cur_arg += 2;
1286 continue;
1287 }
1288
1289 if (!strcmp(args[cur_arg], "gid")) {
1290
1291 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1292 cur_arg += 2;
1293 continue;
1294 }
1295
1296 if (!strcmp(args[cur_arg], "user")) {
1297 struct passwd *user;
1298
1299 user = getpwnam(args[cur_arg + 1]);
1300 if (!user) {
1301 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1302 file, linenum, args[0], args[cur_arg + 1 ]);
1303 err_code |= ERR_ALERT | ERR_FATAL;
1304 goto out;
1305 }
1306
1307 global.unix_bind.ux.uid = user->pw_uid;
1308 cur_arg += 2;
1309 continue;
1310 }
1311
1312 if (!strcmp(args[cur_arg], "group")) {
1313 struct group *group;
1314
1315 group = getgrnam(args[cur_arg + 1]);
1316 if (!group) {
1317 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1318 file, linenum, args[0], args[cur_arg + 1 ]);
1319 err_code |= ERR_ALERT | ERR_FATAL;
1320 goto out;
1321 }
1322
1323 global.unix_bind.ux.gid = group->gr_gid;
1324 cur_arg += 2;
1325 continue;
1326 }
1327
Willy Tarreaub48f9582011-09-05 01:17:06 +02001328 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001329 file, linenum, args[0]);
1330 err_code |= ERR_ALERT | ERR_FATAL;
1331 goto out;
1332 }
1333 }
William Lallemand0f99e342011-10-12 17:50:54 +02001334 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1335 /* delete previous herited or defined syslog servers */
1336 struct logsrv *back;
1337 struct logsrv *tmp;
1338
1339 if (*(args[1]) != 0) {
1340 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
1343 }
1344
1345 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1346 LIST_DEL(&tmp->list);
1347 free(tmp);
1348 }
1349 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001350 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001351 struct sockaddr_storage *sk;
1352 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001353 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001354 int arg = 0;
1355 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001356
Willy Tarreaubaaee002006-06-26 02:48:02 +02001357 if (*(args[1]) == 0 || *(args[2]) == 0) {
1358 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001359 err_code |= ERR_ALERT | ERR_FATAL;
1360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001361 }
William Lallemand0f99e342011-10-12 17:50:54 +02001362
1363 logsrv = calloc(1, sizeof(struct logsrv));
1364
Willy Tarreau18324f52014-06-27 18:10:07 +02001365 /* just after the address, a length may be specified */
1366 if (strcmp(args[arg+2], "len") == 0) {
1367 len = atoi(args[arg+3]);
1368 if (len < 80 || len > 65535) {
1369 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1370 file, linenum, args[arg+3]);
1371 err_code |= ERR_ALERT | ERR_FATAL;
1372 goto out;
1373 }
1374 logsrv->maxlen = len;
1375
1376 /* skip these two args */
1377 arg += 2;
1378 }
1379 else
1380 logsrv->maxlen = MAX_SYSLOG_LEN;
1381
1382 if (logsrv->maxlen > global.max_syslog_len) {
1383 global.max_syslog_len = logsrv->maxlen;
1384 logline = realloc(logline, global.max_syslog_len + 1);
1385 }
1386
1387 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001388 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001389 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001390 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001391 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392 }
1393
William Lallemand0f99e342011-10-12 17:50:54 +02001394 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001395 if (*(args[arg+3])) {
1396 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001397 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001398 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001399 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001400 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401 }
1402 }
1403
William Lallemand0f99e342011-10-12 17:50:54 +02001404 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001405 if (*(args[arg+4])) {
1406 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001407 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001408 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001409 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001410 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001411 }
1412 }
1413
Willy Tarreau902636f2013-03-10 19:44:48 +01001414 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001415 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001416 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001417 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001418 free(logsrv);
1419 goto out;
1420 }
1421 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001422
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001423 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001424 if (port1 != port2) {
1425 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1426 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001427 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001428 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001429 goto out;
1430 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001431
William Lallemand0f99e342011-10-12 17:50:54 +02001432 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001433 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001434 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001435 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001436
William Lallemand0f99e342011-10-12 17:50:54 +02001437 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001438 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001439 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1440 char *name;
1441 int len;
1442
1443 if (global.log_send_hostname != NULL) {
1444 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1445 err_code |= ERR_ALERT;
1446 goto out;
1447 }
1448
1449 if (*(args[1]))
1450 name = args[1];
1451 else
1452 name = hostname;
1453
1454 len = strlen(name);
1455
1456 /* We'll add a space after the name to respect the log format */
1457 free(global.log_send_hostname);
1458 global.log_send_hostname = malloc(len + 2);
1459 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1460 }
Kevinm48936af2010-12-22 16:08:21 +00001461 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1462 if (*(args[1]) == 0) {
1463 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1464 err_code |= ERR_ALERT | ERR_FATAL;
1465 goto out;
1466 }
1467 free(global.log_tag);
1468 global.log_tag = strdup(args[1]);
1469 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001470 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1471 if (global.spread_checks != 0) {
1472 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001473 err_code |= ERR_ALERT;
1474 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001475 }
1476 if (*(args[1]) == 0) {
1477 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001478 err_code |= ERR_ALERT | ERR_FATAL;
1479 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001480 }
1481 global.spread_checks = atol(args[1]);
1482 if (global.spread_checks < 0 || global.spread_checks > 50) {
1483 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001484 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001485 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001486 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001487 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1488 const char *err;
1489 unsigned int val;
1490
1491
1492 if (*(args[1]) == 0) {
1493 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1494 err_code |= ERR_ALERT | ERR_FATAL;
1495 goto out;
1496 }
1497
1498 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1499 if (err) {
1500 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1501 err_code |= ERR_ALERT | ERR_FATAL;
1502 }
1503 global.max_spread_checks = val;
1504 if (global.max_spread_checks < 0) {
1505 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1506 err_code |= ERR_ALERT | ERR_FATAL;
1507 }
1508 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001509 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1510#ifdef USE_CPU_AFFINITY
1511 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001512 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001513 unsigned long cpus = 0;
1514
1515 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001516 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001517 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001518 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001519 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001520 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001521 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001522 proc = atol(args[1]);
1523 if (proc >= 1 && proc <= LONGBITS)
1524 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001525 }
1526
1527 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001528 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1529 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
1532 }
1533
1534 cur_arg = 2;
1535 while (*args[cur_arg]) {
1536 unsigned int low, high;
1537
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001538 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001539 char *dash = strchr(args[cur_arg], '-');
1540
1541 low = high = str2uic(args[cur_arg]);
1542 if (dash)
1543 high = str2uic(dash + 1);
1544
1545 if (high < low) {
1546 unsigned int swap = low;
1547 low = high;
1548 high = swap;
1549 }
1550
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001551 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001552 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001553 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001554 err_code |= ERR_ALERT | ERR_FATAL;
1555 goto out;
1556 }
1557
1558 while (low <= high)
1559 cpus |= 1UL << low++;
1560 }
1561 else {
1562 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1563 file, linenum, args[0], args[cur_arg]);
1564 err_code |= ERR_ALERT | ERR_FATAL;
1565 goto out;
1566 }
1567 cur_arg++;
1568 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001569 for (i = 0; i < LONGBITS; i++)
1570 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001571 global.cpu_map[i] = cpus;
1572#else
1573 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1574 err_code |= ERR_ALERT | ERR_FATAL;
1575 goto out;
1576#endif
1577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001579 struct cfg_kw_list *kwl;
1580 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001581 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001582
1583 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1584 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1585 if (kwl->kw[index].section != CFG_GLOBAL)
1586 continue;
1587 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001588 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001589 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001590 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001591 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001592 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001593 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001594 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001595 err_code |= ERR_WARN;
1596 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001597 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001598 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001599 }
1600 }
1601 }
1602
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001604 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001606
Willy Tarreau058e9072009-07-20 09:30:05 +02001607 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001608 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001609 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001610}
1611
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001612void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001613{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001614 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615 defproxy.mode = PR_MODE_TCP;
1616 defproxy.state = PR_STNEW;
1617 defproxy.maxconn = cfg_maxpconn;
1618 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001619 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001620
Simon Horman66183002013-02-23 10:16:43 +09001621 defproxy.defsrv.check.inter = DEF_CHKINTR;
1622 defproxy.defsrv.check.fastinter = 0;
1623 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001624 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1625 defproxy.defsrv.agent.fastinter = 0;
1626 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001627 defproxy.defsrv.check.rise = DEF_RISETIME;
1628 defproxy.defsrv.check.fall = DEF_FALLTIME;
1629 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1630 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001631 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001632 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001633 defproxy.defsrv.maxqueue = 0;
1634 defproxy.defsrv.minconn = 0;
1635 defproxy.defsrv.maxconn = 0;
1636 defproxy.defsrv.slowstart = 0;
1637 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1638 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1639 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001640
1641 defproxy.email_alert.level = LOG_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001642}
1643
Willy Tarreauade5ec42010-01-28 19:33:49 +01001644
Willy Tarreau63af98d2014-05-18 08:11:41 +02001645/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1646 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1647 * ERR_FATAL in case of error.
1648 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001649static int create_cond_regex_rule(const char *file, int line,
1650 struct proxy *px, int dir, int action, int flags,
1651 const char *cmd, const char *reg, const char *repl,
1652 const char **cond_start)
1653{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001654 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001655 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001656 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001657 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001658 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001659 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001660 int cs;
1661 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001662
1663 if (px == &defproxy) {
1664 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001665 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001666 goto err;
1667 }
1668
1669 if (*reg == 0) {
1670 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001671 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001672 goto err;
1673 }
1674
1675 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001676 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001677
Willy Tarreau5321c422010-01-28 20:35:13 +01001678 if (cond_start &&
1679 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001680 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1681 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1682 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001683 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001684 goto err;
1685 }
1686 }
1687 else if (cond_start && **cond_start) {
1688 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1689 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001690 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001691 goto err;
1692 }
1693
Willy Tarreau63af98d2014-05-18 08:11:41 +02001694 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001695 (dir == SMP_OPT_DIR_REQ) ?
1696 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1697 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1698 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001699
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001700 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001701 if (!preg) {
1702 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001703 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001704 goto err;
1705 }
1706
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001707 cs = !(flags & REG_ICASE);
1708 cap = !(flags & REG_NOSUB);
1709 error = NULL;
1710 if (!regex_comp(reg, preg, cs, cap, &error)) {
1711 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1712 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001713 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001714 goto err;
1715 }
1716
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001717 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001718 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001719 if (repl && err) {
1720 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1721 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001722 ret_code |= ERR_ALERT | ERR_FATAL;
1723 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001724 }
1725
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001726 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001727 ret_code |= ERR_WARN;
1728
1729 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001730
Willy Tarreau63af98d2014-05-18 08:11:41 +02001731 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001732 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001733 err:
1734 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001735 free(errmsg);
1736 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001737}
1738
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001740 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001741 * Returns the error code, 0 if OK, or any combination of :
1742 * - ERR_ABORT: must abort ASAP
1743 * - ERR_FATAL: we can continue parsing but not start the service
1744 * - ERR_WARN: a warning has been emitted
1745 * - ERR_ALERT: an alert has been emitted
1746 * Only the two first ones can stop processing, the two others are just
1747 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001748 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001749int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1750{
1751 static struct peers *curpeers = NULL;
1752 struct peer *newpeer = NULL;
1753 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001754 struct bind_conf *bind_conf;
1755 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001756 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001757 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001758
1759 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001760 if (!*args[1]) {
1761 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001762 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001763 goto out;
1764 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001765
1766 err = invalid_char(args[1]);
1767 if (err) {
1768 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1769 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001770 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001771 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001772 }
1773
1774 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1775 /*
1776 * If there are two proxies with the same name only following
1777 * combinations are allowed:
1778 */
1779 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001780 Alert("Parsing [%s:%d]: peers section '%s' has the same name as another peers section declared at %s:%d.\n",
Emeric Brun32da3c42010-09-23 18:39:19 +02001781 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001782 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001783 }
1784 }
1785
1786 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1787 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1788 err_code |= ERR_ALERT | ERR_ABORT;
1789 goto out;
1790 }
1791
1792 curpeers->next = peers;
1793 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001794 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001795 curpeers->conf.line = linenum;
1796 curpeers->last_change = now.tv_sec;
1797 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001798 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001799 }
1800 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001801 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001802 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001803 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001804
1805 if (!*args[2]) {
1806 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1807 file, linenum, args[0]);
1808 err_code |= ERR_ALERT | ERR_FATAL;
1809 goto out;
1810 }
1811
1812 err = invalid_char(args[1]);
1813 if (err) {
1814 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1815 file, linenum, *err, args[1]);
1816 err_code |= ERR_ALERT | ERR_FATAL;
1817 goto out;
1818 }
1819
1820 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1821 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1822 err_code |= ERR_ALERT | ERR_ABORT;
1823 goto out;
1824 }
1825
1826 /* the peers are linked backwards first */
1827 curpeers->count++;
1828 newpeer->next = curpeers->remote;
1829 curpeers->remote = newpeer;
1830 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001831 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001832 newpeer->conf.line = linenum;
1833
1834 newpeer->last_change = now.tv_sec;
1835 newpeer->id = strdup(args[1]);
1836
Willy Tarreau902636f2013-03-10 19:44:48 +01001837 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001838 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001839 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001840 err_code |= ERR_ALERT | ERR_FATAL;
1841 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001842 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001843
1844 proto = protocol_by_family(sk->ss_family);
1845 if (!proto || !proto->connect) {
1846 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1847 file, linenum, args[0], args[1]);
1848 err_code |= ERR_ALERT | ERR_FATAL;
1849 goto out;
1850 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001851
1852 if (port1 != port2) {
1853 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1854 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001855 err_code |= ERR_ALERT | ERR_FATAL;
1856 goto out;
1857 }
1858
Willy Tarreau2aa38802013-02-20 19:20:59 +01001859 if (!port1) {
1860 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1861 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001862 err_code |= ERR_ALERT | ERR_FATAL;
1863 goto out;
1864 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001865
Emeric Brun32da3c42010-09-23 18:39:19 +02001866 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001867 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001868 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001869 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001870
Emeric Brun32da3c42010-09-23 18:39:19 +02001871 if (strcmp(newpeer->id, localpeer) == 0) {
1872 /* Current is local peer, it define a frontend */
1873 newpeer->local = 1;
1874
1875 if (!curpeers->peers_fe) {
1876 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1877 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1878 err_code |= ERR_ALERT | ERR_ABORT;
1879 goto out;
1880 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001881
Willy Tarreau237250c2011-07-29 01:49:03 +02001882 init_new_proxy(curpeers->peers_fe);
1883 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001884 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001885 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1886 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01001887 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02001888
1889 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1890
Willy Tarreau902636f2013-03-10 19:44:48 +01001891 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1892 if (errmsg && *errmsg) {
1893 indent_msg(&errmsg, 2);
1894 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001895 }
1896 else
1897 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1898 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001899 err_code |= ERR_FATAL;
1900 goto out;
1901 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001902
1903 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001904 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001905 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1906 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02001907 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02001908 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001909 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01001910 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001911 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1912 global.maxsock += l->maxconn;
1913 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001914 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001915 else {
1916 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1917 file, linenum, args[0], args[1],
1918 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1919 err_code |= ERR_FATAL;
1920 goto out;
1921 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001922 }
1923 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001924 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
1925 curpeers->state = PR_STSTOPPED;
1926 }
1927 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
1928 curpeers->state = PR_STNEW;
1929 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001930 else if (*args[0] != 0) {
1931 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1932 err_code |= ERR_ALERT | ERR_FATAL;
1933 goto out;
1934 }
1935
1936out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001937 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001938 return err_code;
1939}
1940
Simon Horman0d16a402015-01-30 11:22:58 +09001941
1942/*
1943 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
1944 * Returns the error code, 0 if OK, or any combination of :
1945 * - ERR_ABORT: must abort ASAP
1946 * - ERR_FATAL: we can continue parsing but not start the service
1947 * - ERR_WARN: a warning has been emitted
1948 * - ERR_ALERT: an alert has been emitted
1949 * Only the two first ones can stop processing, the two others are just
1950 * indicators.
1951 */
1952int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
1953{
1954 static struct mailers *curmailers = NULL;
1955 struct mailer *newmailer = NULL;
1956 const char *err;
1957 int err_code = 0;
1958 char *errmsg = NULL;
1959
1960 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
1961 if (!*args[1]) {
1962 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
1963 err_code |= ERR_ALERT | ERR_ABORT;
1964 goto out;
1965 }
1966
1967 err = invalid_char(args[1]);
1968 if (err) {
1969 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1970 file, linenum, *err, args[0], args[1]);
1971 err_code |= ERR_ALERT | ERR_ABORT;
1972 goto out;
1973 }
1974
1975 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
1976 /*
1977 * If there are two proxies with the same name only following
1978 * combinations are allowed:
1979 */
1980 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001981 Alert("Parsing [%s:%d]: mailers section '%s' has the same name as another mailers section declared at %s:%d.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09001982 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001983 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09001984 }
1985 }
1986
1987 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
1988 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1989 err_code |= ERR_ALERT | ERR_ABORT;
1990 goto out;
1991 }
1992
1993 curmailers->next = mailers;
1994 mailers = curmailers;
1995 curmailers->conf.file = strdup(file);
1996 curmailers->conf.line = linenum;
1997 curmailers->id = strdup(args[1]);
1998 }
1999 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2000 struct sockaddr_storage *sk;
2001 int port1, port2;
2002 struct protocol *proto;
2003
2004 if (!*args[2]) {
2005 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2006 file, linenum, args[0]);
2007 err_code |= ERR_ALERT | ERR_FATAL;
2008 goto out;
2009 }
2010
2011 err = invalid_char(args[1]);
2012 if (err) {
2013 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2014 file, linenum, *err, args[1]);
2015 err_code |= ERR_ALERT | ERR_FATAL;
2016 goto out;
2017 }
2018
2019 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2020 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2021 err_code |= ERR_ALERT | ERR_ABORT;
2022 goto out;
2023 }
2024
2025 /* the mailers are linked backwards first */
2026 curmailers->count++;
2027 newmailer->next = curmailers->mailer_list;
2028 curmailers->mailer_list = newmailer;
2029 newmailer->mailers = curmailers;
2030 newmailer->conf.file = strdup(file);
2031 newmailer->conf.line = linenum;
2032
2033 newmailer->id = strdup(args[1]);
2034
2035 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2036 if (!sk) {
2037 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2038 err_code |= ERR_ALERT | ERR_FATAL;
2039 goto out;
2040 }
2041
2042 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002043 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2044 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002045 file, linenum, args[0], args[1]);
2046 err_code |= ERR_ALERT | ERR_FATAL;
2047 goto out;
2048 }
2049
2050 if (port1 != port2) {
2051 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2052 file, linenum, args[0], args[1], args[2]);
2053 err_code |= ERR_ALERT | ERR_FATAL;
2054 goto out;
2055 }
2056
2057 if (!port1) {
2058 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2059 file, linenum, args[0], args[1], args[2]);
2060 err_code |= ERR_ALERT | ERR_FATAL;
2061 goto out;
2062 }
2063
2064 newmailer->addr = *sk;
2065 newmailer->proto = proto;
2066 newmailer->xprt = &raw_sock;
2067 newmailer->sock_init_arg = NULL;
2068 } /* neither "mailer" nor "mailers" */
2069 else if (*args[0] != 0) {
2070 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2071 err_code |= ERR_ALERT | ERR_FATAL;
2072 goto out;
2073 }
2074
2075out:
2076 free(errmsg);
2077 return err_code;
2078}
2079
Simon Horman9dc49962015-01-30 11:22:59 +09002080static void free_email_alert(struct proxy *p)
2081{
2082 free(p->email_alert.mailers.name);
2083 p->email_alert.mailers.name = NULL;
2084 free(p->email_alert.from);
2085 p->email_alert.from = NULL;
2086 free(p->email_alert.to);
2087 p->email_alert.to = NULL;
2088 free(p->email_alert.myhostname);
2089 p->email_alert.myhostname = NULL;
2090}
2091
Willy Tarreau3842f002009-06-14 11:39:52 +02002092int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002093{
2094 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002095 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002096 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002097 int rc;
2098 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002099 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002100 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002101 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002102 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002103 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104
Willy Tarreau977b8e42006-12-29 14:19:17 +01002105 if (!strcmp(args[0], "listen"))
2106 rc = PR_CAP_LISTEN;
2107 else if (!strcmp(args[0], "frontend"))
2108 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002109 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002110 rc = PR_CAP_BE | PR_CAP_RS;
2111 else if (!strcmp(args[0], "ruleset"))
2112 rc = PR_CAP_RS;
2113 else
2114 rc = PR_CAP_NONE;
2115
2116 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002117 if (!*args[1]) {
2118 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2119 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2120 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002121 err_code |= ERR_ALERT | ERR_ABORT;
2122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002123 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002124
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002125 err = invalid_char(args[1]);
2126 if (err) {
2127 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2128 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002129 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002130 }
2131
Willy Tarreau8f50b682015-05-26 11:45:02 +02002132 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2133 if (curproxy) {
2134 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2135 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2136 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002137 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002138 }
2139
Willy Tarreaubaaee002006-06-26 02:48:02 +02002140 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2141 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002142 err_code |= ERR_ALERT | ERR_ABORT;
2143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002144 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002145
Willy Tarreau97cb7802010-01-03 20:23:58 +01002146 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002147 curproxy->next = proxy;
2148 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002149 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2150 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002151 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002152 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002153 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002154 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002155
2156 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002157 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002158 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02002159
Willy Tarreau4348fad2012-09-20 16:48:07 +02002160 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2161
Willy Tarreau902636f2013-03-10 19:44:48 +01002162 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2163 if (errmsg && *errmsg) {
2164 indent_msg(&errmsg, 2);
2165 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002166 }
2167 else
2168 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2169 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002170 err_code |= ERR_FATAL;
2171 goto out;
2172 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002173
Willy Tarreau4348fad2012-09-20 16:48:07 +02002174 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002175 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002176 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002177 }
2178
2179 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002180 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002181 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002182
Willy Tarreaubaaee002006-06-26 02:48:02 +02002183 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002184 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002185 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002186 curproxy->no_options = defproxy.no_options;
2187 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002188 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002189 curproxy->except_net = defproxy.except_net;
2190 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002191 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002192 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002193
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002194 if (defproxy.fwdfor_hdr_len) {
2195 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2196 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2197 }
2198
Willy Tarreaub86db342009-11-30 11:50:16 +01002199 if (defproxy.orgto_hdr_len) {
2200 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2201 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2202 }
2203
Mark Lamourinec2247f02012-01-04 13:02:01 -05002204 if (defproxy.server_id_hdr_len) {
2205 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2206 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2207 }
2208
Willy Tarreau977b8e42006-12-29 14:19:17 +01002209 if (curproxy->cap & PR_CAP_FE) {
2210 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002211 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002212 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002213
2214 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002215 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2216 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002217
2218 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2219 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002220
Willy Tarreau977b8e42006-12-29 14:19:17 +01002221 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002222 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002223 curproxy->fullconn = defproxy.fullconn;
2224 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002225 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002226 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002227
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002228 if (defproxy.check_req) {
2229 curproxy->check_req = calloc(1, defproxy.check_len);
2230 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2231 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002232 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002234 if (defproxy.expect_str) {
2235 curproxy->expect_str = strdup(defproxy.expect_str);
2236 if (defproxy.expect_regex) {
2237 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002238 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2239 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002240 }
2241 }
2242
Willy Tarreau67402132012-05-31 20:40:20 +02002243 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002244 if (defproxy.cookie_name)
2245 curproxy->cookie_name = strdup(defproxy.cookie_name);
2246 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002247 if (defproxy.cookie_domain)
2248 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002249
Willy Tarreau31936852010-10-06 16:59:56 +02002250 if (defproxy.cookie_maxidle)
2251 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2252
2253 if (defproxy.cookie_maxlife)
2254 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2255
Emeric Brun647caf12009-06-30 17:57:00 +02002256 if (defproxy.rdp_cookie_name)
2257 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2258 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2259
Willy Tarreau01732802007-11-01 22:48:15 +01002260 if (defproxy.url_param_name)
2261 curproxy->url_param_name = strdup(defproxy.url_param_name);
2262 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002263
Benoitaffb4812009-03-25 13:02:10 +01002264 if (defproxy.hh_name)
2265 curproxy->hh_name = strdup(defproxy.hh_name);
2266 curproxy->hh_len = defproxy.hh_len;
2267 curproxy->hh_match_domain = defproxy.hh_match_domain;
2268
Willy Tarreauef9a3602012-12-08 22:29:20 +01002269 if (defproxy.conn_src.iface_name)
2270 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2271 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002272 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002273#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002274 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002275#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002278 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002279 if (defproxy.capture_name)
2280 curproxy->capture_name = strdup(defproxy.capture_name);
2281 curproxy->capture_namelen = defproxy.capture_namelen;
2282 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002284
Willy Tarreau977b8e42006-12-29 14:19:17 +01002285 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002286 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002287 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002288 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002289 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002290 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002291 curproxy->mon_net = defproxy.mon_net;
2292 curproxy->mon_mask = defproxy.mon_mask;
2293 if (defproxy.monitor_uri)
2294 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2295 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002296 if (defproxy.defbe.name)
2297 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002298
2299 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002300 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2301 if (curproxy->conf.logformat_string &&
2302 curproxy->conf.logformat_string != default_http_log_format &&
2303 curproxy->conf.logformat_string != default_tcp_log_format &&
2304 curproxy->conf.logformat_string != clf_http_log_format)
2305 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2306
2307 if (defproxy.conf.lfs_file) {
2308 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2309 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2310 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002311 }
2312
2313 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002314 curproxy->timeout.connect = defproxy.timeout.connect;
2315 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002316 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002317 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002318 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002319 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002320 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002321 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002322 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002323 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002324 }
2325
Willy Tarreaubaaee002006-06-26 02:48:02 +02002326 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002327 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002328
2329 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002330 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002331 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002332 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002333 LIST_INIT(&node->list);
2334 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2335 }
2336
Willy Tarreau62a61232013-04-12 18:13:46 +02002337 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2338 if (curproxy->conf.uniqueid_format_string)
2339 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2340
Willy Tarreau094af4e2015-01-07 15:03:42 +01002341 if (defproxy.log_tag)
2342 curproxy->log_tag = strdup(defproxy.log_tag);
2343
Willy Tarreau62a61232013-04-12 18:13:46 +02002344 if (defproxy.conf.uif_file) {
2345 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2346 curproxy->conf.uif_line = defproxy.conf.uif_line;
2347 }
William Lallemanda73203e2012-03-12 12:48:57 +01002348
2349 /* copy default header unique id */
2350 if (defproxy.header_unique_id)
2351 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2352
William Lallemand82fe75c2012-10-23 10:25:10 +02002353 /* default compression options */
2354 if (defproxy.comp != NULL) {
2355 curproxy->comp = calloc(1, sizeof(struct comp));
2356 curproxy->comp->algos = defproxy.comp->algos;
2357 curproxy->comp->types = defproxy.comp->types;
2358 }
2359
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002361 curproxy->conf.used_listener_id = EB_ROOT;
2362 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002363
Simon Horman98637e52014-06-20 12:30:16 +09002364 if (defproxy.check_path)
2365 curproxy->check_path = strdup(defproxy.check_path);
2366 if (defproxy.check_command)
2367 curproxy->check_command = strdup(defproxy.check_command);
2368
Simon Horman9dc49962015-01-30 11:22:59 +09002369 if (defproxy.email_alert.mailers.name)
2370 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2371 if (defproxy.email_alert.from)
2372 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2373 if (defproxy.email_alert.to)
2374 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2375 if (defproxy.email_alert.myhostname)
2376 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002377 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002378
Willy Tarreau93893792009-07-23 13:19:11 +02002379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002380 }
2381 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2382 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002383 /* FIXME-20070101: we should do this too at the end of the
2384 * config parsing to free all default values.
2385 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002386 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002387 free(defproxy.check_command);
2388 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002389 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002390 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002391 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002392 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002393 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002394 free(defproxy.capture_name);
2395 free(defproxy.monitor_uri);
2396 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002397 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002398 free(defproxy.fwdfor_hdr_name);
2399 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002400 free(defproxy.orgto_hdr_name);
2401 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002402 free(defproxy.server_id_hdr_name);
2403 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002404 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002405 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002406 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002407 free(defproxy.expect_regex);
2408 defproxy.expect_regex = NULL;
2409 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002410
Willy Tarreau62a61232013-04-12 18:13:46 +02002411 if (defproxy.conf.logformat_string != default_http_log_format &&
2412 defproxy.conf.logformat_string != default_tcp_log_format &&
2413 defproxy.conf.logformat_string != clf_http_log_format)
2414 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002415
Willy Tarreau62a61232013-04-12 18:13:46 +02002416 free(defproxy.conf.uniqueid_format_string);
2417 free(defproxy.conf.lfs_file);
2418 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002419 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002420 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002421
Willy Tarreaua534fea2008-08-03 12:19:50 +02002422 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002423 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002424
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 /* we cannot free uri_auth because it might already be used */
2426 init_default_instance();
2427 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002428 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2429 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002430 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002432 }
2433 else if (curproxy == NULL) {
2434 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002437 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002438
2439 /* update the current file and line being parsed */
2440 curproxy->conf.args.file = curproxy->conf.file;
2441 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002442
2443 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002444 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2445 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2446 if (err_code & ERR_FATAL)
2447 goto out;
2448 }
2449 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002450 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002451 int cur_arg;
2452
Willy Tarreaubaaee002006-06-26 02:48:02 +02002453 if (curproxy == &defproxy) {
2454 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002455 err_code |= ERR_ALERT | ERR_FATAL;
2456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002457 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002458 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002459 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460
Willy Tarreau24709282013-03-10 21:32:12 +01002461 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002462 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002467
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002468 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002469
2470 /* use default settings for unix sockets */
2471 bind_conf->ux.uid = global.unix_bind.ux.uid;
2472 bind_conf->ux.gid = global.unix_bind.ux.gid;
2473 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002474
2475 /* NOTE: the following line might create several listeners if there
2476 * are comma-separated IPs or port ranges. So all further processing
2477 * will have to be applied to all listeners created after last_listen.
2478 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002479 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2480 if (errmsg && *errmsg) {
2481 indent_msg(&errmsg, 2);
2482 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002483 }
2484 else
2485 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2486 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
2489 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002490
Willy Tarreau4348fad2012-09-20 16:48:07 +02002491 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2492 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002493 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002494 }
2495
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002496 cur_arg = 2;
2497 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002498 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002499 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002500 char *err;
2501
Willy Tarreau26982662012-09-12 23:17:10 +02002502 kw = bind_find_kw(args[cur_arg]);
2503 if (kw) {
2504 char *err = NULL;
2505 int code;
2506
2507 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002508 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2509 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002510 cur_arg += 1 + kw->skip ;
2511 err_code |= ERR_ALERT | ERR_FATAL;
2512 goto out;
2513 }
2514
Willy Tarreau4348fad2012-09-20 16:48:07 +02002515 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002516 err_code |= code;
2517
2518 if (code) {
2519 if (err && *err) {
2520 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002521 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002522 }
2523 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002524 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2525 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002526 if (code & ERR_FATAL) {
2527 free(err);
2528 cur_arg += 1 + kw->skip;
2529 goto out;
2530 }
2531 }
2532 free(err);
2533 cur_arg += 1 + kw->skip;
2534 continue;
2535 }
2536
Willy Tarreau8638f482012-09-18 18:01:17 +02002537 err = NULL;
2538 if (!bind_dumped) {
2539 bind_dump_kws(&err);
2540 indent_msg(&err, 4);
2541 bind_dumped = 1;
2542 }
2543
2544 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2545 file, linenum, args[0], args[1], args[cur_arg],
2546 err ? " Registered keywords :" : "", err ? err : "");
2547 free(err);
2548
Willy Tarreau93893792009-07-23 13:19:11 +02002549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002551 }
Willy Tarreau93893792009-07-23 13:19:11 +02002552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 }
2554 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002555 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2557 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002558 err_code |= ERR_ALERT | ERR_FATAL;
2559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002561 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002562 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002563
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 /* flush useless bits */
2565 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002568 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002569 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002570 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002571
Willy Tarreau1c47f852006-07-09 08:22:27 +02002572 if (!*args[1]) {
2573 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2574 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002575 err_code |= ERR_ALERT | ERR_FATAL;
2576 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002577 }
2578
Willy Tarreaua534fea2008-08-03 12:19:50 +02002579 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002580 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002581 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002582 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002583 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2584
Willy Tarreau93893792009-07-23 13:19:11 +02002585 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2588 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2589 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2590 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2591 else {
2592 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002593 err_code |= ERR_ALERT | ERR_FATAL;
2594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 }
2596 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002597 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002598 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002599
2600 if (curproxy == &defproxy) {
2601 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2602 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002605 }
2606
2607 if (!*args[1]) {
2608 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2609 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002610 err_code |= ERR_ALERT | ERR_FATAL;
2611 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002612 }
2613
2614 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002615 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002616
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002617 if (curproxy->uuid <= 0) {
2618 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002619 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002620 err_code |= ERR_ALERT | ERR_FATAL;
2621 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002622 }
2623
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002624 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2625 if (node) {
2626 struct proxy *target = container_of(node, struct proxy, conf.id);
2627 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2628 file, linenum, proxy_type_str(curproxy), curproxy->id,
2629 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
2632 }
2633 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002634 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002635 else if (!strcmp(args[0], "description")) {
2636 int i, len=0;
2637 char *d;
2638
Cyril Bonté99ed3272010-01-24 23:29:44 +01002639 if (curproxy == &defproxy) {
2640 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2641 file, linenum, args[0]);
2642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
2644 }
2645
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002646 if (!*args[1]) {
2647 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2648 file, linenum, args[0]);
2649 return -1;
2650 }
2651
Willy Tarreau348acfe2014-04-14 15:00:39 +02002652 for (i = 1; *args[i]; i++)
2653 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002654
2655 d = (char *)calloc(1, len);
2656 curproxy->desc = d;
2657
Willy Tarreau348acfe2014-04-14 15:00:39 +02002658 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2659 for (i = 2; *args[i]; i++)
2660 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002661
2662 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002663 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2664 curproxy->state = PR_STSTOPPED;
2665 }
2666 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2667 curproxy->state = PR_STNEW;
2668 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002669 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2670 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002671 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002672
2673 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002674 unsigned int low, high;
2675
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002676 if (strcmp(args[cur_arg], "all") == 0) {
2677 set = 0;
2678 break;
2679 }
2680 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002681 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002682 }
2683 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002684 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002685 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002686 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002687 char *dash = strchr(args[cur_arg], '-');
2688
2689 low = high = str2uic(args[cur_arg]);
2690 if (dash)
2691 high = str2uic(dash + 1);
2692
2693 if (high < low) {
2694 unsigned int swap = low;
2695 low = high;
2696 high = swap;
2697 }
2698
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002699 if (low < 1 || high > LONGBITS) {
2700 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2701 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002702 err_code |= ERR_ALERT | ERR_FATAL;
2703 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002704 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002705 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002706 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002707 }
2708 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002709 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2710 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002711 err_code |= ERR_ALERT | ERR_FATAL;
2712 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002713 }
2714 cur_arg++;
2715 }
2716 curproxy->bind_proc = set;
2717 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002718 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002719 if (curproxy == &defproxy) {
2720 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002721 err_code |= ERR_ALERT | ERR_FATAL;
2722 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002723 }
2724
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002725 err = invalid_char(args[1]);
2726 if (err) {
2727 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2728 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002729 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002730 }
2731
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002732 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002733 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2734 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002735 err_code |= ERR_ALERT | ERR_FATAL;
2736 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002737 }
2738 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002739 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2740 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002741
Willy Tarreau977b8e42006-12-29 14:19:17 +01002742 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002743 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002744
Willy Tarreaubaaee002006-06-26 02:48:02 +02002745 if (*(args[1]) == 0) {
2746 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2747 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002748 err_code |= ERR_ALERT | ERR_FATAL;
2749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002750 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002751
Willy Tarreau67402132012-05-31 20:40:20 +02002752 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002753 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002754 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002755 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 curproxy->cookie_name = strdup(args[1]);
2757 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002758
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 cur_arg = 2;
2760 while (*(args[cur_arg])) {
2761 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002762 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 }
2764 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002765 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002766 }
2767 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002768 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002769 }
2770 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002771 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002772 }
2773 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002774 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002775 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002776 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002777 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002778 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002779 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002780 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002781 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002782 else if (!strcmp(args[cur_arg], "httponly")) {
2783 curproxy->ck_opts |= PR_CK_HTTPONLY;
2784 }
2785 else if (!strcmp(args[cur_arg], "secure")) {
2786 curproxy->ck_opts |= PR_CK_SECURE;
2787 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002788 else if (!strcmp(args[cur_arg], "domain")) {
2789 if (!*args[cur_arg + 1]) {
2790 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2791 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002794 }
2795
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002796 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002797 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002798 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2799 " dots nor does not start with a dot."
2800 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002801 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002802 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002803 }
2804
2805 err = invalid_domainchar(args[cur_arg + 1]);
2806 if (err) {
2807 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2808 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002809 err_code |= ERR_ALERT | ERR_FATAL;
2810 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002811 }
2812
Willy Tarreau68a897b2009-12-03 23:28:34 +01002813 if (!curproxy->cookie_domain) {
2814 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2815 } else {
2816 /* one domain was already specified, add another one by
2817 * building the string which will be returned along with
2818 * the cookie.
2819 */
2820 char *new_ptr;
2821 int new_len = strlen(curproxy->cookie_domain) +
2822 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2823 new_ptr = malloc(new_len);
2824 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2825 free(curproxy->cookie_domain);
2826 curproxy->cookie_domain = new_ptr;
2827 }
Willy Tarreau31936852010-10-06 16:59:56 +02002828 cur_arg++;
2829 }
2830 else if (!strcmp(args[cur_arg], "maxidle")) {
2831 unsigned int maxidle;
2832 const char *res;
2833
2834 if (!*args[cur_arg + 1]) {
2835 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2836 file, linenum, args[cur_arg]);
2837 err_code |= ERR_ALERT | ERR_FATAL;
2838 goto out;
2839 }
2840
2841 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2842 if (res) {
2843 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2844 file, linenum, *res, args[cur_arg]);
2845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
2847 }
2848 curproxy->cookie_maxidle = maxidle;
2849 cur_arg++;
2850 }
2851 else if (!strcmp(args[cur_arg], "maxlife")) {
2852 unsigned int maxlife;
2853 const char *res;
2854
2855 if (!*args[cur_arg + 1]) {
2856 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2857 file, linenum, args[cur_arg]);
2858 err_code |= ERR_ALERT | ERR_FATAL;
2859 goto out;
2860 }
2861
2862 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2863 if (res) {
2864 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2865 file, linenum, *res, args[cur_arg]);
2866 err_code |= ERR_ALERT | ERR_FATAL;
2867 goto out;
2868 }
2869 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002870 cur_arg++;
2871 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002873 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002874 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002875 err_code |= ERR_ALERT | ERR_FATAL;
2876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002877 }
2878 cur_arg++;
2879 }
Willy Tarreau67402132012-05-31 20:40:20 +02002880 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002881 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2882 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002883 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002884 }
2885
Willy Tarreau67402132012-05-31 20:40:20 +02002886 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002887 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2888 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002889 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002891
Willy Tarreau67402132012-05-31 20:40:20 +02002892 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002893 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2894 file, linenum);
2895 err_code |= ERR_ALERT | ERR_FATAL;
2896 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09002898 else if (!strcmp(args[0], "email-alert")) {
2899 if (*(args[1]) == 0) {
2900 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2901 file, linenum, args[0]);
2902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
2904 }
2905
2906 if (!strcmp(args[1], "from")) {
2907 if (*(args[1]) == 0) {
2908 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2909 file, linenum, args[1]);
2910 err_code |= ERR_ALERT | ERR_FATAL;
2911 goto out;
2912 }
2913 free(curproxy->email_alert.from);
2914 curproxy->email_alert.from = strdup(args[2]);
2915 }
2916 else if (!strcmp(args[1], "mailers")) {
2917 if (*(args[1]) == 0) {
2918 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2919 file, linenum, args[1]);
2920 err_code |= ERR_ALERT | ERR_FATAL;
2921 goto out;
2922 }
2923 free(curproxy->email_alert.mailers.name);
2924 curproxy->email_alert.mailers.name = strdup(args[2]);
2925 }
2926 else if (!strcmp(args[1], "myhostname")) {
2927 if (*(args[1]) == 0) {
2928 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2929 file, linenum, args[1]);
2930 err_code |= ERR_ALERT | ERR_FATAL;
2931 goto out;
2932 }
2933 free(curproxy->email_alert.myhostname);
2934 curproxy->email_alert.myhostname = strdup(args[2]);
2935 }
Simon Horman64e34162015-02-06 11:11:57 +09002936 else if (!strcmp(args[1], "level")) {
2937 curproxy->email_alert.level = get_log_level(args[2]);
2938 if (curproxy->email_alert.level < 0) {
2939 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
2940 file, linenum, args[1], args[2]);
2941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
2943 }
2944 }
Simon Horman9dc49962015-01-30 11:22:59 +09002945 else if (!strcmp(args[1], "to")) {
2946 if (*(args[1]) == 0) {
2947 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2948 file, linenum, args[1]);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952 free(curproxy->email_alert.to);
2953 curproxy->email_alert.to = strdup(args[2]);
2954 }
2955 else {
2956 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
2957 file, linenum, args[1]);
2958 err_code |= ERR_ALERT | ERR_FATAL;
2959 goto out;
2960 }
Simon Horman64e34162015-02-06 11:11:57 +09002961 /* Indicate that the email_alert is at least partially configured */
2962 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09002963 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09002964 else if (!strcmp(args[0], "external-check")) {
2965 if (*(args[1]) == 0) {
2966 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2967 file, linenum, args[0]);
2968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
2970 }
2971
2972 if (!strcmp(args[1], "command")) {
2973 if (*(args[1]) == 0) {
2974 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2975 file, linenum, args[1]);
2976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
2978 }
2979 free(curproxy->check_command);
2980 curproxy->check_command = strdup(args[2]);
2981 }
2982 else if (!strcmp(args[1], "path")) {
2983 if (*(args[1]) == 0) {
2984 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2985 file, linenum, args[1]);
2986 err_code |= ERR_ALERT | ERR_FATAL;
2987 goto out;
2988 }
2989 free(curproxy->check_path);
2990 curproxy->check_path = strdup(args[2]);
2991 }
2992 else {
2993 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
2994 file, linenum, args[1]);
2995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
2997 }
2998 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002999 else if (!strcmp(args[0], "persist")) { /* persist */
3000 if (*(args[1]) == 0) {
3001 Alert("parsing [%s:%d] : missing persist method.\n",
3002 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003005 }
3006
3007 if (!strncmp(args[1], "rdp-cookie", 10)) {
3008 curproxy->options2 |= PR_O2_RDPC_PRST;
3009
Emeric Brunb982a3d2010-01-04 15:45:53 +01003010 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003011 const char *beg, *end;
3012
3013 beg = args[1] + 11;
3014 end = strchr(beg, ')');
3015
3016 if (!end || end == beg) {
3017 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3018 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003021 }
3022
3023 free(curproxy->rdp_cookie_name);
3024 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3025 curproxy->rdp_cookie_len = end-beg;
3026 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003027 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003028 free(curproxy->rdp_cookie_name);
3029 curproxy->rdp_cookie_name = strdup("msts");
3030 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3031 }
3032 else { /* syntax */
3033 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3034 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003037 }
3038 }
3039 else {
3040 Alert("parsing [%s:%d] : unknown persist method.\n",
3041 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003042 err_code |= ERR_ALERT | ERR_FATAL;
3043 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003044 }
3045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003047 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003048
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003049 if (curproxy == &defproxy) {
3050 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3051 err_code |= ERR_ALERT | ERR_FATAL;
3052 goto out;
3053 }
3054
Willy Tarreau977b8e42006-12-29 14:19:17 +01003055 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003056 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003057
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003059 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003060 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 }
3064 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003065 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066 curproxy->appsession_name = strdup(args[1]);
3067 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3068 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003069 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3070 if (err) {
3071 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3072 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003073 err_code |= ERR_ALERT | ERR_FATAL;
3074 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003075 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003076 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003077
Willy Tarreau51041c72007-09-09 21:56:53 +02003078 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3079 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003080 err_code |= ERR_ALERT | ERR_ABORT;
3081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003083
3084 cur_arg = 6;
3085 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003086 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3087 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003088 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003089 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003090 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003091 } else if (!strcmp(args[cur_arg], "prefix")) {
3092 curproxy->options2 |= PR_O2_AS_PFX;
3093 } else if (!strcmp(args[cur_arg], "mode")) {
3094 if (!*args[cur_arg + 1]) {
3095 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3096 file, linenum, args[0], args[cur_arg]);
3097 err_code |= ERR_ALERT | ERR_FATAL;
3098 goto out;
3099 }
3100
3101 cur_arg++;
3102 if (!strcmp(args[cur_arg], "query-string")) {
3103 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3104 curproxy->options2 |= PR_O2_AS_M_QS;
3105 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3106 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3107 curproxy->options2 |= PR_O2_AS_M_PP;
3108 } else {
3109 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
3112 }
3113 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003114 cur_arg++;
3115 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 } /* Url App Session */
3117 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003118 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003119 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003120
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003122 if (curproxy == &defproxy) {
3123 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3124 err_code |= ERR_ALERT | ERR_FATAL;
3125 goto out;
3126 }
3127
Willy Tarreaubaaee002006-06-26 02:48:02 +02003128 if (*(args[4]) == 0) {
3129 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3130 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003133 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003134 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 curproxy->capture_name = strdup(args[2]);
3136 curproxy->capture_namelen = strlen(curproxy->capture_name);
3137 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138 curproxy->to_log |= LW_COOKIE;
3139 }
3140 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3141 struct cap_hdr *hdr;
3142
3143 if (curproxy == &defproxy) {
3144 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 }
3148
3149 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3150 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3151 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003152 err_code |= ERR_ALERT | ERR_FATAL;
3153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 }
3155
3156 hdr = calloc(sizeof(struct cap_hdr), 1);
3157 hdr->next = curproxy->req_cap;
3158 hdr->name = strdup(args[3]);
3159 hdr->namelen = strlen(args[3]);
3160 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003161 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 hdr->index = curproxy->nb_req_cap++;
3163 curproxy->req_cap = hdr;
3164 curproxy->to_log |= LW_REQHDR;
3165 }
3166 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3167 struct cap_hdr *hdr;
3168
3169 if (curproxy == &defproxy) {
3170 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003171 err_code |= ERR_ALERT | ERR_FATAL;
3172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 }
3174
3175 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3176 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3177 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003178 err_code |= ERR_ALERT | ERR_FATAL;
3179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 }
3181 hdr = calloc(sizeof(struct cap_hdr), 1);
3182 hdr->next = curproxy->rsp_cap;
3183 hdr->name = strdup(args[3]);
3184 hdr->namelen = strlen(args[3]);
3185 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003186 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003187 hdr->index = curproxy->nb_rsp_cap++;
3188 curproxy->rsp_cap = hdr;
3189 curproxy->to_log |= LW_RSPHDR;
3190 }
3191 else {
3192 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3193 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003194 err_code |= ERR_ALERT | ERR_FATAL;
3195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 }
3197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003199 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003200 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003201
Willy Tarreaubaaee002006-06-26 02:48:02 +02003202 if (*(args[1]) == 0) {
3203 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3204 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 }
3208 curproxy->conn_retries = atol(args[1]);
3209 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003210 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003211 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003212
3213 if (curproxy == &defproxy) {
3214 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
3217 }
3218
Willy Tarreau20b0de52012-12-24 15:45:22 +01003219 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3220 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3221 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3222 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003223 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003224 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3225 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003226 file, linenum, args[0]);
3227 err_code |= ERR_WARN;
3228 }
3229
Willy Tarreauff011f22011-01-06 17:51:27 +01003230 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003231
Willy Tarreauff011f22011-01-06 17:51:27 +01003232 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003233 err_code |= ERR_ALERT | ERR_ABORT;
3234 goto out;
3235 }
3236
Willy Tarreau5002f572014-04-23 01:32:02 +02003237 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003238 err_code |= warnif_cond_conflicts(rule->cond,
3239 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3240 file, linenum);
3241
Willy Tarreauff011f22011-01-06 17:51:27 +01003242 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003243 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003244 else if (!strcmp(args[0], "http-response")) { /* response access control */
3245 struct http_res_rule *rule;
3246
3247 if (curproxy == &defproxy) {
3248 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3249 err_code |= ERR_ALERT | ERR_FATAL;
3250 goto out;
3251 }
3252
3253 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3254 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3255 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3256 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3257 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3258 file, linenum, args[0]);
3259 err_code |= ERR_WARN;
3260 }
3261
3262 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3263
3264 if (!rule) {
3265 err_code |= ERR_ALERT | ERR_ABORT;
3266 goto out;
3267 }
3268
3269 err_code |= warnif_cond_conflicts(rule->cond,
3270 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3271 file, linenum);
3272
3273 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3274 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003275 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3276 /* set the header name and length into the proxy structure */
3277 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3278 err_code |= ERR_WARN;
3279
3280 if (!*args[1]) {
3281 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3282 file, linenum, args[0]);
3283 err_code |= ERR_ALERT | ERR_FATAL;
3284 goto out;
3285 }
3286
3287 /* set the desired header name */
3288 free(curproxy->server_id_hdr_name);
3289 curproxy->server_id_hdr_name = strdup(args[1]);
3290 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3291 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003292 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003293 struct http_req_rule *rule;
3294
Willy Tarreaub099aca2008-10-12 17:26:37 +02003295 if (curproxy == &defproxy) {
3296 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003297 err_code |= ERR_ALERT | ERR_FATAL;
3298 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003299 }
3300
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003301 /* emulate "block" using "http-request block". Since these rules are supposed to
3302 * be processed before all http-request rules, we put them into their own list
3303 * and will insert them at the end.
3304 */
3305 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3306 if (!rule) {
3307 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003308 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003309 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003310 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3311 err_code |= warnif_cond_conflicts(rule->cond,
3312 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3313 file, linenum);
3314 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003315
3316 if (!already_warned(WARN_BLOCK_DEPRECATED))
3317 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of 'http-request deny' which uses the exact same syntax. The rules are translated but support might disappear in a future version.\n", file, linenum, args[0]);
3318
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003319 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003320 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003321 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003322
Cyril Bonté99ed3272010-01-24 23:29:44 +01003323 if (curproxy == &defproxy) {
3324 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
3327 }
3328
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003329 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003330 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3331 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003332 err_code |= ERR_ALERT | ERR_FATAL;
3333 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003334 }
3335
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003336 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003337 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003338 err_code |= warnif_cond_conflicts(rule->cond,
3339 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3340 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003341 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003342 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003343 struct switching_rule *rule;
3344
Willy Tarreaub099aca2008-10-12 17:26:37 +02003345 if (curproxy == &defproxy) {
3346 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003349 }
3350
Willy Tarreau55ea7572007-06-17 19:56:27 +02003351 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003352 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003353
3354 if (*(args[1]) == 0) {
3355 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003356 err_code |= ERR_ALERT | ERR_FATAL;
3357 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003358 }
3359
Willy Tarreauf51658d2014-04-23 01:21:56 +02003360 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3361 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3362 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3363 file, linenum, errmsg);
3364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
3366 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003367
Willy Tarreauf51658d2014-04-23 01:21:56 +02003368 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003369 }
3370
3371 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3372 rule->cond = cond;
3373 rule->be.name = strdup(args[1]);
3374 LIST_INIT(&rule->list);
3375 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3376 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003377 else if (strcmp(args[0], "use-server") == 0) {
3378 struct server_rule *rule;
3379
3380 if (curproxy == &defproxy) {
3381 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3382 err_code |= ERR_ALERT | ERR_FATAL;
3383 goto out;
3384 }
3385
3386 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3387 err_code |= ERR_WARN;
3388
3389 if (*(args[1]) == 0) {
3390 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
3393 }
3394
3395 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3396 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3397 file, linenum, args[0]);
3398 err_code |= ERR_ALERT | ERR_FATAL;
3399 goto out;
3400 }
3401
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003402 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3403 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3404 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
3407 }
3408
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003409 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003410
3411 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3412 rule->cond = cond;
3413 rule->srv.name = strdup(args[1]);
3414 LIST_INIT(&rule->list);
3415 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3416 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3417 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003418 else if ((!strcmp(args[0], "force-persist")) ||
3419 (!strcmp(args[0], "ignore-persist"))) {
3420 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003421
3422 if (curproxy == &defproxy) {
3423 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3424 err_code |= ERR_ALERT | ERR_FATAL;
3425 goto out;
3426 }
3427
3428 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3429 err_code |= ERR_WARN;
3430
Willy Tarreauef6494c2010-01-28 17:12:36 +01003431 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003432 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3433 file, linenum, args[0]);
3434 err_code |= ERR_ALERT | ERR_FATAL;
3435 goto out;
3436 }
3437
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003438 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3439 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3440 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003441 err_code |= ERR_ALERT | ERR_FATAL;
3442 goto out;
3443 }
3444
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003445 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3446 * where force-persist is applied.
3447 */
3448 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003449
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003450 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003451 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003452 if (!strcmp(args[0], "force-persist")) {
3453 rule->type = PERSIST_TYPE_FORCE;
3454 } else {
3455 rule->type = PERSIST_TYPE_IGNORE;
3456 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003457 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003458 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003459 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003460 else if (!strcmp(args[0], "stick-table")) {
3461 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003462 struct proxy *other;
3463
3464 other = find_stktable(curproxy->id);
3465 if (other) {
3466 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3467 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3468 err_code |= ERR_ALERT | ERR_FATAL;
3469 goto out;
3470 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003471
Emeric Brun32da3c42010-09-23 18:39:19 +02003472 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003473 curproxy->table.type = (unsigned int)-1;
3474 while (*args[myidx]) {
3475 const char *err;
3476
3477 if (strcmp(args[myidx], "size") == 0) {
3478 myidx++;
3479 if (!*(args[myidx])) {
3480 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3481 file, linenum, args[myidx-1]);
3482 err_code |= ERR_ALERT | ERR_FATAL;
3483 goto out;
3484 }
3485 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3486 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3487 file, linenum, *err, args[myidx-1]);
3488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
3490 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003491 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003492 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003493 else if (strcmp(args[myidx], "peers") == 0) {
3494 myidx++;
Godbach50523162013-12-11 19:48:57 +08003495 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003496 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3497 file, linenum, args[myidx-1]);
3498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
Godbach50523162013-12-11 19:48:57 +08003500 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003501 curproxy->table.peers.name = strdup(args[myidx++]);
3502 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003503 else if (strcmp(args[myidx], "expire") == 0) {
3504 myidx++;
3505 if (!*(args[myidx])) {
3506 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3507 file, linenum, args[myidx-1]);
3508 err_code |= ERR_ALERT | ERR_FATAL;
3509 goto out;
3510 }
3511 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3512 if (err) {
3513 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3514 file, linenum, *err, args[myidx-1]);
3515 err_code |= ERR_ALERT | ERR_FATAL;
3516 goto out;
3517 }
3518 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003519 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003520 }
3521 else if (strcmp(args[myidx], "nopurge") == 0) {
3522 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003523 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003524 }
3525 else if (strcmp(args[myidx], "type") == 0) {
3526 myidx++;
3527 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3528 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3529 file, linenum, args[myidx]);
3530 err_code |= ERR_ALERT | ERR_FATAL;
3531 goto out;
3532 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003533 /* myidx already points to next arg */
3534 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003535 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003536 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003537 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003538
3539 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003540 nw = args[myidx];
3541 while (*nw) {
3542 /* the "store" keyword supports a comma-separated list */
3543 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003544 sa = NULL; /* store arg */
3545 while (*nw && *nw != ',') {
3546 if (*nw == '(') {
3547 *nw = 0;
3548 sa = ++nw;
3549 while (*nw != ')') {
3550 if (!*nw) {
3551 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3552 file, linenum, args[0], cw);
3553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
3555 }
3556 nw++;
3557 }
3558 *nw = '\0';
3559 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003560 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003561 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003562 if (*nw)
3563 *nw++ = '\0';
3564 type = stktable_get_data_type(cw);
3565 if (type < 0) {
3566 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3567 file, linenum, args[0], cw);
3568 err_code |= ERR_ALERT | ERR_FATAL;
3569 goto out;
3570 }
Willy Tarreauac782882010-06-20 10:41:54 +02003571
3572 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3573 switch (err) {
3574 case PE_NONE: break;
3575 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003576 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3577 file, linenum, args[0], cw);
3578 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003579 break;
3580
3581 case PE_ARG_MISSING:
3582 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3583 file, linenum, args[0], cw);
3584 err_code |= ERR_ALERT | ERR_FATAL;
3585 goto out;
3586
3587 case PE_ARG_NOT_USED:
3588 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3589 file, linenum, args[0], cw);
3590 err_code |= ERR_ALERT | ERR_FATAL;
3591 goto out;
3592
3593 default:
3594 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3595 file, linenum, args[0], cw);
3596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003598 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003599 }
3600 myidx++;
3601 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003602 else {
3603 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3604 file, linenum, args[myidx]);
3605 err_code |= ERR_ALERT | ERR_FATAL;
3606 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003607 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003608 }
3609
3610 if (!curproxy->table.size) {
3611 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3612 file, linenum);
3613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
3615 }
3616
3617 if (curproxy->table.type == (unsigned int)-1) {
3618 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3619 file, linenum);
3620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
3622 }
3623 }
3624 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003625 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003626 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003627 int myidx = 0;
3628 const char *name = NULL;
3629 int flags;
3630
3631 if (curproxy == &defproxy) {
3632 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
3635 }
3636
3637 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3638 err_code |= ERR_WARN;
3639 goto out;
3640 }
3641
3642 myidx++;
3643 if ((strcmp(args[myidx], "store") == 0) ||
3644 (strcmp(args[myidx], "store-request") == 0)) {
3645 myidx++;
3646 flags = STK_IS_STORE;
3647 }
3648 else if (strcmp(args[myidx], "store-response") == 0) {
3649 myidx++;
3650 flags = STK_IS_STORE | STK_ON_RSP;
3651 }
3652 else if (strcmp(args[myidx], "match") == 0) {
3653 myidx++;
3654 flags = STK_IS_MATCH;
3655 }
3656 else if (strcmp(args[myidx], "on") == 0) {
3657 myidx++;
3658 flags = STK_IS_MATCH | STK_IS_STORE;
3659 }
3660 else {
3661 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3662 err_code |= ERR_ALERT | ERR_FATAL;
3663 goto out;
3664 }
3665
3666 if (*(args[myidx]) == 0) {
3667 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3668 err_code |= ERR_ALERT | ERR_FATAL;
3669 goto out;
3670 }
3671
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003672 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003673 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003674 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003675 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003676 err_code |= ERR_ALERT | ERR_FATAL;
3677 goto out;
3678 }
3679
3680 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003681 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3682 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3683 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003684 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003685 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003686 goto out;
3687 }
3688 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003689 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3690 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3691 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003692 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003693 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003694 goto out;
3695 }
3696 }
3697
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003698 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003699 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003700
Emeric Brunb982a3d2010-01-04 15:45:53 +01003701 if (strcmp(args[myidx], "table") == 0) {
3702 myidx++;
3703 name = args[myidx++];
3704 }
3705
Willy Tarreauef6494c2010-01-28 17:12:36 +01003706 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003707 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3708 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3709 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003710 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003711 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003712 goto out;
3713 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003714 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003715 else if (*(args[myidx])) {
3716 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3717 file, linenum, args[0], args[myidx]);
3718 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003719 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003720 goto out;
3721 }
Emeric Brun97679e72010-09-23 17:56:44 +02003722 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003723 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003724 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003725 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003726
Emeric Brunb982a3d2010-01-04 15:45:53 +01003727 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3728 rule->cond = cond;
3729 rule->expr = expr;
3730 rule->flags = flags;
3731 rule->table.name = name ? strdup(name) : NULL;
3732 LIST_INIT(&rule->list);
3733 if (flags & STK_ON_RSP)
3734 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3735 else
3736 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3737 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003738 else if (!strcmp(args[0], "stats")) {
3739 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3740 curproxy->uri_auth = NULL; /* we must detach from the default config */
3741
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003742 if (!*args[1]) {
3743 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003744 } else if (!strcmp(args[1], "admin")) {
3745 struct stats_admin_rule *rule;
3746
3747 if (curproxy == &defproxy) {
3748 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3749 err_code |= ERR_ALERT | ERR_FATAL;
3750 goto out;
3751 }
3752
3753 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3754 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3755 err_code |= ERR_ALERT | ERR_ABORT;
3756 goto out;
3757 }
3758
3759 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3760 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3761 file, linenum, args[0], args[1]);
3762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
3764 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003765 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3766 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3767 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003768 err_code |= ERR_ALERT | ERR_FATAL;
3769 goto out;
3770 }
3771
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003772 err_code |= warnif_cond_conflicts(cond,
3773 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3774 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003775
3776 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3777 rule->cond = cond;
3778 LIST_INIT(&rule->list);
3779 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003780 } else if (!strcmp(args[1], "uri")) {
3781 if (*(args[2]) == 0) {
3782 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003783 err_code |= ERR_ALERT | ERR_FATAL;
3784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003785 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3786 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_ABORT;
3788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003789 }
3790 } else if (!strcmp(args[1], "realm")) {
3791 if (*(args[2]) == 0) {
3792 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003795 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3796 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003797 err_code |= ERR_ALERT | ERR_ABORT;
3798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003799 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003800 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003801 unsigned interval;
3802
3803 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3804 if (err) {
3805 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3806 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003809 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3810 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003811 err_code |= ERR_ALERT | ERR_ABORT;
3812 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003813 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003814 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003815 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003816
3817 if (curproxy == &defproxy) {
3818 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3819 err_code |= ERR_ALERT | ERR_FATAL;
3820 goto out;
3821 }
3822
3823 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3824 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3825 err_code |= ERR_ALERT | ERR_ABORT;
3826 goto out;
3827 }
3828
Willy Tarreauff011f22011-01-06 17:51:27 +01003829 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3830 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003831 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3832 file, linenum, args[0]);
3833 err_code |= ERR_WARN;
3834 }
3835
Willy Tarreauff011f22011-01-06 17:51:27 +01003836 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003837
Willy Tarreauff011f22011-01-06 17:51:27 +01003838 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003839 err_code |= ERR_ALERT | ERR_ABORT;
3840 goto out;
3841 }
3842
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003843 err_code |= warnif_cond_conflicts(rule->cond,
3844 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3845 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003846 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003847
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 } else if (!strcmp(args[1], "auth")) {
3849 if (*(args[2]) == 0) {
3850 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003851 err_code |= ERR_ALERT | ERR_FATAL;
3852 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003853 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3854 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003855 err_code |= ERR_ALERT | ERR_ABORT;
3856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003857 }
3858 } else if (!strcmp(args[1], "scope")) {
3859 if (*(args[2]) == 0) {
3860 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003861 err_code |= ERR_ALERT | ERR_FATAL;
3862 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003863 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3864 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003865 err_code |= ERR_ALERT | ERR_ABORT;
3866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003867 }
3868 } else if (!strcmp(args[1], "enable")) {
3869 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3870 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_ALERT | ERR_ABORT;
3872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003874 } else if (!strcmp(args[1], "hide-version")) {
3875 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3876 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003877 err_code |= ERR_ALERT | ERR_ABORT;
3878 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003879 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003880 } else if (!strcmp(args[1], "show-legends")) {
3881 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3882 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3883 err_code |= ERR_ALERT | ERR_ABORT;
3884 goto out;
3885 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003886 } else if (!strcmp(args[1], "show-node")) {
3887
3888 if (*args[2]) {
3889 int i;
3890 char c;
3891
3892 for (i=0; args[2][i]; i++) {
3893 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003894 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3895 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003896 break;
3897 }
3898
3899 if (!i || args[2][i]) {
3900 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3901 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3902 file, linenum, args[0], args[1]);
3903 err_code |= ERR_ALERT | ERR_FATAL;
3904 goto out;
3905 }
3906 }
3907
3908 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3909 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3910 err_code |= ERR_ALERT | ERR_ABORT;
3911 goto out;
3912 }
3913 } else if (!strcmp(args[1], "show-desc")) {
3914 char *desc = NULL;
3915
3916 if (*args[2]) {
3917 int i, len=0;
3918 char *d;
3919
Willy Tarreau348acfe2014-04-14 15:00:39 +02003920 for (i = 2; *args[i]; i++)
3921 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003922
3923 desc = d = (char *)calloc(1, len);
3924
Willy Tarreau348acfe2014-04-14 15:00:39 +02003925 d += snprintf(d, desc + len - d, "%s", args[2]);
3926 for (i = 3; *args[i]; i++)
3927 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003928 }
3929
3930 if (!*args[2] && !global.desc)
3931 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3932 file, linenum, args[1]);
3933 else {
3934 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3935 free(desc);
3936 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3937 err_code |= ERR_ALERT | ERR_ABORT;
3938 goto out;
3939 }
3940 free(desc);
3941 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003942 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003943stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003944 Alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003945 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003948 }
3949 }
3950 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003951 int optnum;
3952
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003953 if (*(args[1]) == '\0') {
3954 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3955 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003956 err_code |= ERR_ALERT | ERR_FATAL;
3957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003958 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003959
3960 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3961 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003962 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3963 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3964 file, linenum, cfg_opts[optnum].name);
3965 err_code |= ERR_ALERT | ERR_FATAL;
3966 goto out;
3967 }
Willy Tarreau93893792009-07-23 13:19:11 +02003968 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3969 err_code |= ERR_WARN;
3970 goto out;
3971 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003972
Willy Tarreau3842f002009-06-14 11:39:52 +02003973 curproxy->no_options &= ~cfg_opts[optnum].val;
3974 curproxy->options &= ~cfg_opts[optnum].val;
3975
3976 switch (kwm) {
3977 case KWM_STD:
3978 curproxy->options |= cfg_opts[optnum].val;
3979 break;
3980 case KWM_NO:
3981 curproxy->no_options |= cfg_opts[optnum].val;
3982 break;
3983 case KWM_DEF: /* already cleared */
3984 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003985 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003986
Willy Tarreau93893792009-07-23 13:19:11 +02003987 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003988 }
3989 }
3990
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003991 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3992 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003993 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3994 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3995 file, linenum, cfg_opts2[optnum].name);
3996 err_code |= ERR_ALERT | ERR_FATAL;
3997 goto out;
3998 }
Willy Tarreau93893792009-07-23 13:19:11 +02003999 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4000 err_code |= ERR_WARN;
4001 goto out;
4002 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004003
Willy Tarreau3842f002009-06-14 11:39:52 +02004004 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4005 curproxy->options2 &= ~cfg_opts2[optnum].val;
4006
4007 switch (kwm) {
4008 case KWM_STD:
4009 curproxy->options2 |= cfg_opts2[optnum].val;
4010 break;
4011 case KWM_NO:
4012 curproxy->no_options2 |= cfg_opts2[optnum].val;
4013 break;
4014 case KWM_DEF: /* already cleared */
4015 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004016 }
Willy Tarreau93893792009-07-23 13:19:11 +02004017 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004018 }
4019 }
4020
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004021 /* HTTP options override each other. They can be cancelled using
4022 * "no option xxx" which only switches to default mode if the mode
4023 * was this one (useful for cancelling options set in defaults
4024 * sections).
4025 */
4026 if (strcmp(args[1], "httpclose") == 0) {
4027 if (kwm == KWM_STD) {
4028 curproxy->options &= ~PR_O_HTTP_MODE;
4029 curproxy->options |= PR_O_HTTP_PCL;
4030 goto out;
4031 }
4032 else if (kwm == KWM_NO) {
4033 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4034 curproxy->options &= ~PR_O_HTTP_MODE;
4035 goto out;
4036 }
4037 }
4038 else if (strcmp(args[1], "forceclose") == 0) {
4039 if (kwm == KWM_STD) {
4040 curproxy->options &= ~PR_O_HTTP_MODE;
4041 curproxy->options |= PR_O_HTTP_FCL;
4042 goto out;
4043 }
4044 else if (kwm == KWM_NO) {
4045 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4046 curproxy->options &= ~PR_O_HTTP_MODE;
4047 goto out;
4048 }
4049 }
4050 else if (strcmp(args[1], "http-server-close") == 0) {
4051 if (kwm == KWM_STD) {
4052 curproxy->options &= ~PR_O_HTTP_MODE;
4053 curproxy->options |= PR_O_HTTP_SCL;
4054 goto out;
4055 }
4056 else if (kwm == KWM_NO) {
4057 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4058 curproxy->options &= ~PR_O_HTTP_MODE;
4059 goto out;
4060 }
4061 }
4062 else if (strcmp(args[1], "http-keep-alive") == 0) {
4063 if (kwm == KWM_STD) {
4064 curproxy->options &= ~PR_O_HTTP_MODE;
4065 curproxy->options |= PR_O_HTTP_KAL;
4066 goto out;
4067 }
4068 else if (kwm == KWM_NO) {
4069 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4070 curproxy->options &= ~PR_O_HTTP_MODE;
4071 goto out;
4072 }
4073 }
4074 else if (strcmp(args[1], "http-tunnel") == 0) {
4075 if (kwm == KWM_STD) {
4076 curproxy->options &= ~PR_O_HTTP_MODE;
4077 curproxy->options |= PR_O_HTTP_TUN;
4078 goto out;
4079 }
4080 else if (kwm == KWM_NO) {
4081 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4082 curproxy->options &= ~PR_O_HTTP_MODE;
4083 goto out;
4084 }
4085 }
4086
Joseph Lynch726ab712015-05-11 23:25:34 -07004087 /* Redispatch can take an integer argument that control when the
4088 * resispatch occurs. All values are relative to the retries option.
4089 * This can be cancelled using "no option xxx".
4090 */
4091 if (strcmp(args[1], "redispatch") == 0) {
4092 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4093 err_code |= ERR_WARN;
4094 goto out;
4095 }
4096
4097 curproxy->no_options &= ~PR_O_REDISP;
4098 curproxy->options &= ~PR_O_REDISP;
4099
4100 switch (kwm) {
4101 case KWM_STD:
4102 curproxy->options |= PR_O_REDISP;
4103 curproxy->redispatch_after = -1;
4104 if(*args[2]) {
4105 curproxy->redispatch_after = atol(args[2]);
4106 }
4107 break;
4108 case KWM_NO:
4109 curproxy->no_options |= PR_O_REDISP;
4110 curproxy->redispatch_after = 0;
4111 break;
4112 case KWM_DEF: /* already cleared */
4113 break;
4114 }
4115 goto out;
4116 }
4117
Willy Tarreau3842f002009-06-14 11:39:52 +02004118 if (kwm != KWM_STD) {
4119 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004120 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004121 err_code |= ERR_ALERT | ERR_FATAL;
4122 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004123 }
4124
Emeric Brun3a058f32009-06-30 18:26:00 +02004125 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004126 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004127 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004128 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004129 if (*(args[2]) != '\0') {
4130 if (!strcmp(args[2], "clf")) {
4131 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004132 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004133 } else {
4134 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02004135 err_code |= ERR_ALERT | ERR_FATAL;
4136 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004137 }
4138 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004139 if (curproxy->conf.logformat_string != default_http_log_format &&
4140 curproxy->conf.logformat_string != default_tcp_log_format &&
4141 curproxy->conf.logformat_string != clf_http_log_format)
4142 free(curproxy->conf.logformat_string);
4143 curproxy->conf.logformat_string = logformat;
4144
4145 free(curproxy->conf.lfs_file);
4146 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4147 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004148 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004149 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004150 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004151 if (curproxy->conf.logformat_string != default_http_log_format &&
4152 curproxy->conf.logformat_string != default_tcp_log_format &&
4153 curproxy->conf.logformat_string != clf_http_log_format)
4154 free(curproxy->conf.logformat_string);
4155 curproxy->conf.logformat_string = default_tcp_log_format;
4156
4157 free(curproxy->conf.lfs_file);
4158 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4159 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004160 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004161 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004162 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004163 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004164 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004165
4166 if (curproxy->cap & PR_CAP_FE)
4167 curproxy->options |= PR_O_TCP_CLI_KA;
4168 if (curproxy->cap & PR_CAP_BE)
4169 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004170 }
4171 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004172 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004173 err_code |= ERR_WARN;
4174
Willy Tarreaubaaee002006-06-26 02:48:02 +02004175 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004176 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004177 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004178 curproxy->options2 &= ~PR_O2_CHK_ANY;
4179 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004180 if (!*args[2]) { /* no argument */
4181 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4182 curproxy->check_len = strlen(DEF_CHECK_REQ);
4183 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004184 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004185 curproxy->check_req = (char *)malloc(reqlen);
4186 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004187 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004188 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004189 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004190 if (*args[4])
4191 reqlen += strlen(args[4]);
4192 else
4193 reqlen += strlen("HTTP/1.0");
4194
4195 curproxy->check_req = (char *)malloc(reqlen);
4196 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004197 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004198 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004199 }
4200 else if (!strcmp(args[1], "ssl-hello-chk")) {
4201 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004202 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004203 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004204
Willy Tarreaua534fea2008-08-03 12:19:50 +02004205 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004206 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004207 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004208 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004209 }
Willy Tarreau23677902007-05-08 23:50:35 +02004210 else if (!strcmp(args[1], "smtpchk")) {
4211 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004212 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004213 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004214 curproxy->options2 &= ~PR_O2_CHK_ANY;
4215 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004216
4217 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4218 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4219 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4220 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4221 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4222 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4223 curproxy->check_req = (char *)malloc(reqlen);
4224 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4225 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4226 } else {
4227 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4228 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4229 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4230 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4231 }
4232 }
4233 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004234 else if (!strcmp(args[1], "pgsql-check")) {
4235 /* use PostgreSQL request to check servers' health */
4236 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4237 err_code |= ERR_WARN;
4238
4239 free(curproxy->check_req);
4240 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004241 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004242 curproxy->options2 |= PR_O2_PGSQL_CHK;
4243
4244 if (*(args[2])) {
4245 int cur_arg = 2;
4246
4247 while (*(args[cur_arg])) {
4248 if (strcmp(args[cur_arg], "user") == 0) {
4249 char * packet;
4250 uint32_t packet_len;
4251 uint32_t pv;
4252
4253 /* suboption header - needs additional argument for it */
4254 if (*(args[cur_arg+1]) == 0) {
4255 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4256 file, linenum, args[0], args[1], args[cur_arg]);
4257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
4259 }
4260
4261 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4262 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4263 pv = htonl(0x30000); /* protocol version 3.0 */
4264
4265 packet = (char*) calloc(1, packet_len);
4266
4267 memcpy(packet + 4, &pv, 4);
4268
4269 /* copy "user" */
4270 memcpy(packet + 8, "user", 4);
4271
4272 /* copy username */
4273 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4274
4275 free(curproxy->check_req);
4276 curproxy->check_req = packet;
4277 curproxy->check_len = packet_len;
4278
4279 packet_len = htonl(packet_len);
4280 memcpy(packet, &packet_len, 4);
4281 cur_arg += 2;
4282 } else {
4283 /* unknown suboption - catchall */
4284 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4285 file, linenum, args[0], args[1]);
4286 err_code |= ERR_ALERT | ERR_FATAL;
4287 goto out;
4288 }
4289 } /* end while loop */
4290 }
4291 }
4292
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004293 else if (!strcmp(args[1], "redis-check")) {
4294 /* use REDIS PING request to check servers' health */
4295 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4296 err_code |= ERR_WARN;
4297
4298 free(curproxy->check_req);
4299 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004300 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004301 curproxy->options2 |= PR_O2_REDIS_CHK;
4302
4303 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4304 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4305 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4306 }
4307
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004308 else if (!strcmp(args[1], "mysql-check")) {
4309 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004310 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4311 err_code |= ERR_WARN;
4312
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004313 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004314 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004315 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004316 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004317
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004318 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004319 * const char mysql40_client_auth_pkt[] = {
4320 * "\x0e\x00\x00" // packet length
4321 * "\x01" // packet number
4322 * "\x00\x00" // client capabilities
4323 * "\x00\x00\x01" // max packet
4324 * "haproxy\x00" // username (null terminated string)
4325 * "\x00" // filler (always 0x00)
4326 * "\x01\x00\x00" // packet length
4327 * "\x00" // packet number
4328 * "\x01" // COM_QUIT command
4329 * };
4330 */
4331
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004332 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4333 * const char mysql41_client_auth_pkt[] = {
4334 * "\x0e\x00\x00\" // packet length
4335 * "\x01" // packet number
4336 * "\x00\x00\x00\x00" // client capabilities
4337 * "\x00\x00\x00\x01" // max packet
4338 * "\x21" // character set (UTF-8)
4339 * char[23] // All zeroes
4340 * "haproxy\x00" // username (null terminated string)
4341 * "\x00" // filler (always 0x00)
4342 * "\x01\x00\x00" // packet length
4343 * "\x00" // packet number
4344 * "\x01" // COM_QUIT command
4345 * };
4346 */
4347
4348
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004349 if (*(args[2])) {
4350 int cur_arg = 2;
4351
4352 while (*(args[cur_arg])) {
4353 if (strcmp(args[cur_arg], "user") == 0) {
4354 char *mysqluser;
4355 int packetlen, reqlen, userlen;
4356
4357 /* suboption header - needs additional argument for it */
4358 if (*(args[cur_arg+1]) == 0) {
4359 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4360 file, linenum, args[0], args[1], args[cur_arg]);
4361 err_code |= ERR_ALERT | ERR_FATAL;
4362 goto out;
4363 }
4364 mysqluser = args[cur_arg + 1];
4365 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004366
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004367 if (*(args[cur_arg+2])) {
4368 if (!strcmp(args[cur_arg+2], "post-41")) {
4369 packetlen = userlen + 7 + 27;
4370 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004371
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004372 free(curproxy->check_req);
4373 curproxy->check_req = (char *)calloc(1, reqlen);
4374 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004375
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004376 snprintf(curproxy->check_req, 4, "%c%c%c",
4377 ((unsigned char) packetlen & 0xff),
4378 ((unsigned char) (packetlen >> 8) & 0xff),
4379 ((unsigned char) (packetlen >> 16) & 0xff));
4380
4381 curproxy->check_req[3] = 1;
4382 curproxy->check_req[5] = 130;
4383 curproxy->check_req[11] = 1;
4384 curproxy->check_req[12] = 33;
4385 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4386 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4387 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4388 cur_arg += 3;
4389 } else {
4390 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4391 err_code |= ERR_ALERT | ERR_FATAL;
4392 goto out;
4393 }
4394 } else {
4395 packetlen = userlen + 7;
4396 reqlen = packetlen + 9;
4397
4398 free(curproxy->check_req);
4399 curproxy->check_req = (char *)calloc(1, reqlen);
4400 curproxy->check_len = reqlen;
4401
4402 snprintf(curproxy->check_req, 4, "%c%c%c",
4403 ((unsigned char) packetlen & 0xff),
4404 ((unsigned char) (packetlen >> 8) & 0xff),
4405 ((unsigned char) (packetlen >> 16) & 0xff));
4406
4407 curproxy->check_req[3] = 1;
4408 curproxy->check_req[5] = 128;
4409 curproxy->check_req[8] = 1;
4410 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4411 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4412 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4413 cur_arg += 2;
4414 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004415 } else {
4416 /* unknown suboption - catchall */
4417 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4418 file, linenum, args[0], args[1]);
4419 err_code |= ERR_ALERT | ERR_FATAL;
4420 goto out;
4421 }
4422 } /* end while loop */
4423 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004424 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004425 else if (!strcmp(args[1], "ldap-check")) {
4426 /* use LDAP request to check servers' health */
4427 free(curproxy->check_req);
4428 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004429 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004430 curproxy->options2 |= PR_O2_LDAP_CHK;
4431
4432 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4433 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4434 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4435 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004436 else if (!strcmp(args[1], "tcp-check")) {
4437 /* use raw TCPCHK send/expect to check servers' health */
4438 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4439 err_code |= ERR_WARN;
4440
4441 free(curproxy->check_req);
4442 curproxy->check_req = NULL;
4443 curproxy->options2 &= ~PR_O2_CHK_ANY;
4444 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4445 }
Simon Horman98637e52014-06-20 12:30:16 +09004446 else if (!strcmp(args[1], "external-check")) {
4447 /* excute an external command to check servers' health */
4448 free(curproxy->check_req);
4449 curproxy->check_req = NULL;
4450 curproxy->options2 &= ~PR_O2_CHK_ANY;
4451 curproxy->options2 |= PR_O2_EXT_CHK;
4452 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004453 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004454 int cur_arg;
4455
4456 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4457 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004458 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004459
Willy Tarreau87cf5142011-08-19 22:57:24 +02004460 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004461
4462 free(curproxy->fwdfor_hdr_name);
4463 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4464 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4465
4466 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4467 cur_arg = 2;
4468 while (*(args[cur_arg])) {
4469 if (!strcmp(args[cur_arg], "except")) {
4470 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004471 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004472 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4473 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004474 err_code |= ERR_ALERT | ERR_FATAL;
4475 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004476 }
4477 /* flush useless bits */
4478 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004479 cur_arg += 2;
4480 } else if (!strcmp(args[cur_arg], "header")) {
4481 /* suboption header - needs additional argument for it */
4482 if (*(args[cur_arg+1]) == 0) {
4483 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4484 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004485 err_code |= ERR_ALERT | ERR_FATAL;
4486 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004487 }
4488 free(curproxy->fwdfor_hdr_name);
4489 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4490 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4491 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004492 } else if (!strcmp(args[cur_arg], "if-none")) {
4493 curproxy->options &= ~PR_O_FF_ALWAYS;
4494 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004495 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004496 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004497 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004498 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004499 err_code |= ERR_ALERT | ERR_FATAL;
4500 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004501 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004502 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004503 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004504 else if (!strcmp(args[1], "originalto")) {
4505 int cur_arg;
4506
4507 /* insert x-original-to field, but not for the IP address listed as an except.
4508 * set default options (ie: bitfield, header name, etc)
4509 */
4510
4511 curproxy->options |= PR_O_ORGTO;
4512
4513 free(curproxy->orgto_hdr_name);
4514 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4515 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4516
Willy Tarreau87cf5142011-08-19 22:57:24 +02004517 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004518 cur_arg = 2;
4519 while (*(args[cur_arg])) {
4520 if (!strcmp(args[cur_arg], "except")) {
4521 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004522 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_to, &curproxy->except_mask_to)) {
Maik Broemme2850cb42009-04-17 18:53:21 +02004523 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4524 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004525 err_code |= ERR_ALERT | ERR_FATAL;
4526 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004527 }
4528 /* flush useless bits */
4529 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4530 cur_arg += 2;
4531 } else if (!strcmp(args[cur_arg], "header")) {
4532 /* suboption header - needs additional argument for it */
4533 if (*(args[cur_arg+1]) == 0) {
4534 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4535 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004536 err_code |= ERR_ALERT | ERR_FATAL;
4537 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004538 }
4539 free(curproxy->orgto_hdr_name);
4540 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4541 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4542 cur_arg += 2;
4543 } else {
4544 /* unknown suboption - catchall */
4545 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4546 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004547 err_code |= ERR_ALERT | ERR_FATAL;
4548 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004549 }
4550 } /* end while loop */
4551 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004552 else {
4553 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004554 err_code |= ERR_ALERT | ERR_FATAL;
4555 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004556 }
Willy Tarreau93893792009-07-23 13:19:11 +02004557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004558 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004559 else if (!strcmp(args[0], "default_backend")) {
4560 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004561 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004562
4563 if (*(args[1]) == 0) {
4564 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004565 err_code |= ERR_ALERT | ERR_FATAL;
4566 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004567 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004568 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004569 curproxy->defbe.name = strdup(args[1]);
4570 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004571 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004572 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004573 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004574
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004575 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4576 Warning("parsing [%s:%d]: keyword '%s' is deprecated in favor of 'option redispatch', and will not be supported by future versions.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004577 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004578 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004579 /* enable reconnections to dispatch */
4580 curproxy->options |= PR_O_REDISP;
4581 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004582 else if (!strcmp(args[0], "http-check")) {
4583 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004584 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004585
4586 if (strcmp(args[1], "disable-on-404") == 0) {
4587 /* enable a graceful server shutdown on an HTTP 404 response */
4588 curproxy->options |= PR_O_DISABLE404;
4589 }
Willy Tarreauef781042010-01-27 11:53:01 +01004590 else if (strcmp(args[1], "send-state") == 0) {
4591 /* enable emission of the apparent state of a server in HTTP checks */
4592 curproxy->options2 |= PR_O2_CHK_SNDST;
4593 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004594 else if (strcmp(args[1], "expect") == 0) {
4595 const char *ptr_arg;
4596 int cur_arg;
4597
4598 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4599 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4600 err_code |= ERR_ALERT | ERR_FATAL;
4601 goto out;
4602 }
4603
4604 cur_arg = 2;
4605 /* consider exclamation marks, sole or at the beginning of a word */
4606 while (*(ptr_arg = args[cur_arg])) {
4607 while (*ptr_arg == '!') {
4608 curproxy->options2 ^= PR_O2_EXP_INV;
4609 ptr_arg++;
4610 }
4611 if (*ptr_arg)
4612 break;
4613 cur_arg++;
4614 }
4615 /* now ptr_arg points to the beginning of a word past any possible
4616 * exclamation mark, and cur_arg is the argument which holds this word.
4617 */
4618 if (strcmp(ptr_arg, "status") == 0) {
4619 if (!*(args[cur_arg + 1])) {
4620 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4621 file, linenum, args[0], args[1], ptr_arg);
4622 err_code |= ERR_ALERT | ERR_FATAL;
4623 goto out;
4624 }
4625 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004626 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004627 curproxy->expect_str = strdup(args[cur_arg + 1]);
4628 }
4629 else if (strcmp(ptr_arg, "string") == 0) {
4630 if (!*(args[cur_arg + 1])) {
4631 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4632 file, linenum, args[0], args[1], ptr_arg);
4633 err_code |= ERR_ALERT | ERR_FATAL;
4634 goto out;
4635 }
4636 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004637 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004638 curproxy->expect_str = strdup(args[cur_arg + 1]);
4639 }
4640 else if (strcmp(ptr_arg, "rstatus") == 0) {
4641 if (!*(args[cur_arg + 1])) {
4642 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4643 file, linenum, args[0], args[1], ptr_arg);
4644 err_code |= ERR_ALERT | ERR_FATAL;
4645 goto out;
4646 }
4647 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004648 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004649 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004650 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004651 free(curproxy->expect_regex);
4652 curproxy->expect_regex = NULL;
4653 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004654 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004655 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4656 error = NULL;
4657 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4658 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4659 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4660 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004661 err_code |= ERR_ALERT | ERR_FATAL;
4662 goto out;
4663 }
4664 }
4665 else if (strcmp(ptr_arg, "rstring") == 0) {
4666 if (!*(args[cur_arg + 1])) {
4667 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4668 file, linenum, args[0], args[1], ptr_arg);
4669 err_code |= ERR_ALERT | ERR_FATAL;
4670 goto out;
4671 }
4672 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004673 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004674 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004675 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004676 free(curproxy->expect_regex);
4677 curproxy->expect_regex = NULL;
4678 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004679 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004680 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4681 error = NULL;
4682 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4683 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4684 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4685 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004686 err_code |= ERR_ALERT | ERR_FATAL;
4687 goto out;
4688 }
4689 }
4690 else {
4691 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4692 file, linenum, args[0], args[1], ptr_arg);
4693 err_code |= ERR_ALERT | ERR_FATAL;
4694 goto out;
4695 }
4696 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004697 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004698 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'send-state', 'expect'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004699 err_code |= ERR_ALERT | ERR_FATAL;
4700 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004701 }
4702 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004703 else if (!strcmp(args[0], "tcp-check")) {
4704 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4705 err_code |= ERR_WARN;
4706
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004707 if (strcmp(args[1], "comment") == 0) {
4708 int cur_arg;
4709 struct tcpcheck_rule *tcpcheck;
4710
4711 cur_arg = 1;
4712 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4713 tcpcheck->action = TCPCHK_ACT_COMMENT;
4714
4715 if (!*args[cur_arg + 1]) {
4716 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4717 file, linenum, args[cur_arg]);
4718 err_code |= ERR_ALERT | ERR_FATAL;
4719 goto out;
4720 }
4721
4722 tcpcheck->comment = strdup(args[cur_arg + 1]);
4723
4724 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4725 }
4726 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004727 const char *ptr_arg;
4728 int cur_arg;
4729 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004730
4731 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02004732 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
4733 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
4734 tcpcheck->action == TCPCHK_ACT_COMMENT) {
4735 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
4736 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004737
Willy Tarreau5581c272015-05-13 12:24:53 +02004738 if (&tcpcheck->list != &curproxy->tcpcheck_rules
4739 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4740 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4741 file, linenum);
4742 err_code |= ERR_ALERT | ERR_FATAL;
4743 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004744 }
4745
4746 cur_arg = 2;
4747 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4748 tcpcheck->action = TCPCHK_ACT_CONNECT;
4749
4750 /* parsing each parameters to fill up the rule */
4751 while (*(ptr_arg = args[cur_arg])) {
4752 /* tcp port */
4753 if (strcmp(args[cur_arg], "port") == 0) {
4754 if ( (atol(args[cur_arg + 1]) > 65535) ||
4755 (atol(args[cur_arg + 1]) < 1) ){
4756 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4757 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4758 err_code |= ERR_ALERT | ERR_FATAL;
4759 goto out;
4760 }
4761 tcpcheck->port = atol(args[cur_arg + 1]);
4762 cur_arg += 2;
4763 }
4764 /* send proxy protocol */
4765 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4766 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4767 cur_arg++;
4768 }
4769#ifdef USE_OPENSSL
4770 else if (strcmp(args[cur_arg], "ssl") == 0) {
4771 curproxy->options |= PR_O_TCPCHK_SSL;
4772 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4773 cur_arg++;
4774 }
4775#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004776 /* comment for this tcpcheck line */
4777 else if (strcmp(args[cur_arg], "comment") == 0) {
4778 if (!*args[cur_arg + 1]) {
4779 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4780 file, linenum, args[cur_arg]);
4781 err_code |= ERR_ALERT | ERR_FATAL;
4782 goto out;
4783 }
4784 tcpcheck->comment = strdup(args[cur_arg + 1]);
4785 cur_arg += 2;
4786 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004787 else {
4788#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004789 Alert("parsing [%s:%d] : '%s %s' expects 'comment', 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004790#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004791 Alert("parsing [%s:%d] : '%s %s' expects 'comment', 'port', 'send-proxy' or but got '%s' as argument.\n",
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004792#endif /* USE_OPENSSL */
4793 file, linenum, args[0], args[1], args[cur_arg]);
4794 err_code |= ERR_ALERT | ERR_FATAL;
4795 goto out;
4796 }
4797
4798 }
4799
4800 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4801 }
4802 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004803 if (! *(args[2]) ) {
4804 /* SEND string expected */
4805 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4806 file, linenum, args[0], args[1], args[2]);
4807 err_code |= ERR_ALERT | ERR_FATAL;
4808 goto out;
4809 } else {
4810 struct tcpcheck_rule *tcpcheck;
4811
4812 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4813
4814 tcpcheck->action = TCPCHK_ACT_SEND;
4815 tcpcheck->string_len = strlen(args[2]);
4816 tcpcheck->string = strdup(args[2]);
4817 tcpcheck->expect_regex = NULL;
4818
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004819 /* comment for this tcpcheck line */
4820 if (strcmp(args[3], "comment") == 0) {
4821 if (!*args[4]) {
4822 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4823 file, linenum, args[3]);
4824 err_code |= ERR_ALERT | ERR_FATAL;
4825 goto out;
4826 }
4827 tcpcheck->comment = strdup(args[4]);
4828 }
4829
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004830 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4831 }
4832 }
4833 else if (strcmp(args[1], "send-binary") == 0) {
4834 if (! *(args[2]) ) {
4835 /* SEND binary string expected */
4836 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4837 file, linenum, args[0], args[1], args[2]);
4838 err_code |= ERR_ALERT | ERR_FATAL;
4839 goto out;
4840 } else {
4841 struct tcpcheck_rule *tcpcheck;
4842 char *err = NULL;
4843
4844 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4845
4846 tcpcheck->action = TCPCHK_ACT_SEND;
4847 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4848 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4849 file, linenum, args[0], args[1], args[2], err);
4850 err_code |= ERR_ALERT | ERR_FATAL;
4851 goto out;
4852 }
4853 tcpcheck->expect_regex = NULL;
4854
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004855 /* comment for this tcpcheck line */
4856 if (strcmp(args[3], "comment") == 0) {
4857 if (!*args[4]) {
4858 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4859 file, linenum, args[3]);
4860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
4862 }
4863 tcpcheck->comment = strdup(args[4]);
4864 }
4865
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004866 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4867 }
4868 }
4869 else if (strcmp(args[1], "expect") == 0) {
4870 const char *ptr_arg;
4871 int cur_arg;
4872 int inverse = 0;
4873
4874 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4875 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4876 err_code |= ERR_ALERT | ERR_FATAL;
4877 goto out;
4878 }
4879
4880 cur_arg = 2;
4881 /* consider exclamation marks, sole or at the beginning of a word */
4882 while (*(ptr_arg = args[cur_arg])) {
4883 while (*ptr_arg == '!') {
4884 inverse = !inverse;
4885 ptr_arg++;
4886 }
4887 if (*ptr_arg)
4888 break;
4889 cur_arg++;
4890 }
4891 /* now ptr_arg points to the beginning of a word past any possible
4892 * exclamation mark, and cur_arg is the argument which holds this word.
4893 */
4894 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004895 struct tcpcheck_rule *tcpcheck;
4896 char *err = NULL;
4897
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004898 if (!*(args[cur_arg + 1])) {
4899 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4900 file, linenum, args[0], args[1], ptr_arg);
4901 err_code |= ERR_ALERT | ERR_FATAL;
4902 goto out;
4903 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004904
4905 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4906
4907 tcpcheck->action = TCPCHK_ACT_EXPECT;
4908 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4909 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4910 file, linenum, args[0], args[1], args[2], err);
4911 err_code |= ERR_ALERT | ERR_FATAL;
4912 goto out;
4913 }
4914 tcpcheck->expect_regex = NULL;
4915 tcpcheck->inverse = inverse;
4916
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004917 /* tcpcheck comment */
4918 cur_arg += 2;
4919 if (strcmp(args[cur_arg], "comment") == 0) {
4920 if (!*args[cur_arg + 1]) {
4921 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4922 file, linenum, args[cur_arg + 1]);
4923 err_code |= ERR_ALERT | ERR_FATAL;
4924 goto out;
4925 }
4926 tcpcheck->comment = strdup(args[cur_arg + 1]);
4927 }
4928
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004929 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4930 }
4931 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004932 struct tcpcheck_rule *tcpcheck;
4933
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004934 if (!*(args[cur_arg + 1])) {
4935 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4936 file, linenum, args[0], args[1], ptr_arg);
4937 err_code |= ERR_ALERT | ERR_FATAL;
4938 goto out;
4939 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004940
4941 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4942
4943 tcpcheck->action = TCPCHK_ACT_EXPECT;
4944 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4945 tcpcheck->string = strdup(args[cur_arg + 1]);
4946 tcpcheck->expect_regex = NULL;
4947 tcpcheck->inverse = inverse;
4948
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004949 /* tcpcheck comment */
4950 cur_arg += 2;
4951 if (strcmp(args[cur_arg], "comment") == 0) {
4952 if (!*args[cur_arg + 1]) {
4953 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4954 file, linenum, args[cur_arg + 1]);
4955 err_code |= ERR_ALERT | ERR_FATAL;
4956 goto out;
4957 }
4958 tcpcheck->comment = strdup(args[cur_arg + 1]);
4959 }
4960
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004961 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4962 }
4963 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004964 struct tcpcheck_rule *tcpcheck;
4965
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004966 if (!*(args[cur_arg + 1])) {
4967 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4968 file, linenum, args[0], args[1], ptr_arg);
4969 err_code |= ERR_ALERT | ERR_FATAL;
4970 goto out;
4971 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004972
4973 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4974
4975 tcpcheck->action = TCPCHK_ACT_EXPECT;
4976 tcpcheck->string_len = 0;
4977 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004978 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4979 error = NULL;
4980 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4981 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4982 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4983 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004984 err_code |= ERR_ALERT | ERR_FATAL;
4985 goto out;
4986 }
4987 tcpcheck->inverse = inverse;
4988
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004989 /* tcpcheck comment */
4990 cur_arg += 2;
4991 if (strcmp(args[cur_arg], "comment") == 0) {
4992 if (!*args[cur_arg + 1]) {
4993 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4994 file, linenum, args[cur_arg + 1]);
4995 err_code |= ERR_ALERT | ERR_FATAL;
4996 goto out;
4997 }
4998 tcpcheck->comment = strdup(args[cur_arg + 1]);
4999 }
5000
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005001 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5002 }
5003 else {
5004 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5005 file, linenum, args[0], args[1], ptr_arg);
5006 err_code |= ERR_ALERT | ERR_FATAL;
5007 goto out;
5008 }
5009 }
5010 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005011 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005012 err_code |= ERR_ALERT | ERR_FATAL;
5013 goto out;
5014 }
5015 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005016 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005017 if (curproxy == &defproxy) {
5018 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005019 err_code |= ERR_ALERT | ERR_FATAL;
5020 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005021 }
5022
Willy Tarreaub80c2302007-11-30 20:51:32 +01005023 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005024 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005025
5026 if (strcmp(args[1], "fail") == 0) {
5027 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005028 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005029 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5030 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005031 err_code |= ERR_ALERT | ERR_FATAL;
5032 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005033 }
5034
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005035 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5036 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5037 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005038 err_code |= ERR_ALERT | ERR_FATAL;
5039 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005040 }
5041 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5042 }
5043 else {
5044 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005045 err_code |= ERR_ALERT | ERR_FATAL;
5046 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005047 }
5048 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005049#ifdef TPROXY
5050 else if (!strcmp(args[0], "transparent")) {
5051 /* enable transparent proxy connections */
5052 curproxy->options |= PR_O_TRANSP;
5053 }
5054#endif
5055 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005056 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005057 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005058
Willy Tarreaubaaee002006-06-26 02:48:02 +02005059 if (*(args[1]) == 0) {
5060 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005061 err_code |= ERR_ALERT | ERR_FATAL;
5062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005063 }
5064 curproxy->maxconn = atol(args[1]);
5065 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005066 else if (!strcmp(args[0], "backlog")) { /* backlog */
5067 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005068 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005069
5070 if (*(args[1]) == 0) {
5071 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005072 err_code |= ERR_ALERT | ERR_FATAL;
5073 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005074 }
5075 curproxy->backlog = atol(args[1]);
5076 }
Willy Tarreau86034312006-12-29 00:10:33 +01005077 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005078 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005079 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005080
Willy Tarreau86034312006-12-29 00:10:33 +01005081 if (*(args[1]) == 0) {
5082 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005083 err_code |= ERR_ALERT | ERR_FATAL;
5084 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005085 }
5086 curproxy->fullconn = atol(args[1]);
5087 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005088 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5089 if (*(args[1]) == 0) {
5090 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005091 err_code |= ERR_ALERT | ERR_FATAL;
5092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005093 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005094 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5095 if (err) {
5096 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5097 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005098 err_code |= ERR_ALERT | ERR_FATAL;
5099 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005100 }
5101 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 }
5103 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005104 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005105 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005106 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005107
Willy Tarreaubaaee002006-06-26 02:48:02 +02005108 if (curproxy == &defproxy) {
5109 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005110 err_code |= ERR_ALERT | ERR_FATAL;
5111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005112 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005113 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005114 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005115
Willy Tarreau902636f2013-03-10 19:44:48 +01005116 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005117 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005118 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005119 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005120 goto out;
5121 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005122
5123 proto = protocol_by_family(sk->ss_family);
5124 if (!proto || !proto->connect) {
5125 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5126 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005127 err_code |= ERR_ALERT | ERR_FATAL;
5128 goto out;
5129 }
5130
5131 if (port1 != port2) {
5132 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5133 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005134 err_code |= ERR_ALERT | ERR_FATAL;
5135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005136 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005137
5138 if (!port1) {
5139 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5140 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005141 err_code |= ERR_ALERT | ERR_FATAL;
5142 goto out;
5143 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005144
Willy Tarreaud5191e72010-02-09 20:50:45 +01005145 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005146 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 }
5148 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005149 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005150 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005151
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005152 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5153 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005156 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005158 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005159 /**
5160 * The syntax for hash-type config element is
5161 * hash-type {map-based|consistent} [[<algo>] avalanche]
5162 *
5163 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5164 */
5165 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005166
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005167 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5168 err_code |= ERR_WARN;
5169
5170 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005171 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5172 }
5173 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005174 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5175 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005176 else if (strcmp(args[1], "avalanche") == 0) {
5177 Alert("parsing [%s:%d] : experimental feature '%s %s' is not supported anymore, please use '%s map-based sdbm avalanche' instead.\n", file, linenum, args[0], args[1], args[0]);
5178 err_code |= ERR_ALERT | ERR_FATAL;
5179 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005180 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005181 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005182 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
5185 }
Bhaskar98634f02013-10-29 23:30:51 -04005186
5187 /* set the hash function to use */
5188 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005189 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005190 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005191
5192 /* if consistent with no argument, then avalanche modifier is also applied */
5193 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5194 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005195 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005196 /* set the hash function */
5197 if (!strcmp(args[2], "sdbm")) {
5198 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5199 }
5200 else if (!strcmp(args[2], "djb2")) {
5201 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005202 }
5203 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005204 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005205 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005206 else if (!strcmp(args[2], "crc32")) {
5207 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5208 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005209 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005210 Alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2', 'crc32', or 'wt6' hash functions.\n", file, linenum, args[0]);
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005211 err_code |= ERR_ALERT | ERR_FATAL;
5212 goto out;
5213 }
5214
5215 /* set the hash modifier */
5216 if (!strcmp(args[3], "avalanche")) {
5217 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5218 }
5219 else if (*args[3]) {
5220 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
5223 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005224 }
William Lallemanda73203e2012-03-12 12:48:57 +01005225 }
William Lallemanda73203e2012-03-12 12:48:57 +01005226 else if (strcmp(args[0], "unique-id-format") == 0) {
5227 if (!*(args[1])) {
5228 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5229 err_code |= ERR_ALERT | ERR_FATAL;
5230 goto out;
5231 }
William Lallemand3203ff42012-11-11 17:30:56 +01005232 if (*(args[2])) {
5233 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5234 err_code |= ERR_ALERT | ERR_FATAL;
5235 goto out;
5236 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005237 free(curproxy->conf.uniqueid_format_string);
5238 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005239
Willy Tarreau62a61232013-04-12 18:13:46 +02005240 free(curproxy->conf.uif_file);
5241 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5242 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005243 }
William Lallemanda73203e2012-03-12 12:48:57 +01005244
5245 else if (strcmp(args[0], "unique-id-header") == 0) {
5246 if (!*(args[1])) {
5247 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5248 err_code |= ERR_ALERT | ERR_FATAL;
5249 goto out;
5250 }
5251 free(curproxy->header_unique_id);
5252 curproxy->header_unique_id = strdup(args[1]);
5253 }
5254
William Lallemand723b73a2012-02-08 16:37:49 +01005255 else if (strcmp(args[0], "log-format") == 0) {
5256 if (!*(args[1])) {
5257 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5258 err_code |= ERR_ALERT | ERR_FATAL;
5259 goto out;
5260 }
William Lallemand3203ff42012-11-11 17:30:56 +01005261 if (*(args[2])) {
5262 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5263 err_code |= ERR_ALERT | ERR_FATAL;
5264 goto out;
5265 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005266
Willy Tarreau62a61232013-04-12 18:13:46 +02005267 if (curproxy->conf.logformat_string != default_http_log_format &&
5268 curproxy->conf.logformat_string != default_tcp_log_format &&
5269 curproxy->conf.logformat_string != clf_http_log_format)
5270 free(curproxy->conf.logformat_string);
5271 curproxy->conf.logformat_string = strdup(args[1]);
5272
5273 free(curproxy->conf.lfs_file);
5274 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5275 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005276
5277 /* get a chance to improve log-format error reporting by
5278 * reporting the correct line-number when possible.
5279 */
5280 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5281 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5282 file, linenum, curproxy->id);
5283 err_code |= ERR_WARN;
5284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005285 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005286 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5287 if (*(args[1]) == 0) {
5288 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5289 err_code |= ERR_ALERT | ERR_FATAL;
5290 goto out;
5291 }
5292 free(curproxy->log_tag);
5293 curproxy->log_tag = strdup(args[1]);
5294 }
William Lallemand0f99e342011-10-12 17:50:54 +02005295 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5296 /* delete previous herited or defined syslog servers */
5297 struct logsrv *back;
5298
5299 if (*(args[1]) != 0) {
5300 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5301 err_code |= ERR_ALERT | ERR_FATAL;
5302 goto out;
5303 }
5304
William Lallemand723b73a2012-02-08 16:37:49 +01005305 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5306 LIST_DEL(&tmplogsrv->list);
5307 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005308 }
5309 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005311 struct logsrv *logsrv;
5312
Willy Tarreaubaaee002006-06-26 02:48:02 +02005313 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005314 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005315 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005316 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005317 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005318 LIST_INIT(&node->list);
5319 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5320 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321 }
5322 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005323 struct sockaddr_storage *sk;
5324 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005325 int arg = 0;
5326 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005327
5328 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005329
Willy Tarreau18324f52014-06-27 18:10:07 +02005330 /* just after the address, a length may be specified */
5331 if (strcmp(args[arg+2], "len") == 0) {
5332 len = atoi(args[arg+3]);
5333 if (len < 80 || len > 65535) {
5334 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5335 file, linenum, args[arg+3]);
5336 err_code |= ERR_ALERT | ERR_FATAL;
5337 goto out;
5338 }
5339 logsrv->maxlen = len;
5340
5341 /* skip these two args */
5342 arg += 2;
5343 }
5344 else
5345 logsrv->maxlen = MAX_SYSLOG_LEN;
5346
5347 if (logsrv->maxlen > global.max_syslog_len) {
5348 global.max_syslog_len = logsrv->maxlen;
5349 logline = realloc(logline, global.max_syslog_len + 1);
5350 }
5351
5352 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005353 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005354 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005355 err_code |= ERR_ALERT | ERR_FATAL;
5356 goto out;
5357
Willy Tarreaubaaee002006-06-26 02:48:02 +02005358 }
5359
William Lallemand0f99e342011-10-12 17:50:54 +02005360 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005361 if (*(args[arg+3])) {
5362 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005363 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005364 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005365 err_code |= ERR_ALERT | ERR_FATAL;
5366 goto out;
5367
Willy Tarreaubaaee002006-06-26 02:48:02 +02005368 }
5369 }
5370
William Lallemand0f99e342011-10-12 17:50:54 +02005371 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005372 if (*(args[arg+4])) {
5373 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005374 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005375 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005376 err_code |= ERR_ALERT | ERR_FATAL;
5377 goto out;
5378
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005379 }
5380 }
5381
Willy Tarreau902636f2013-03-10 19:44:48 +01005382 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005383 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005384 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005385 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005386 goto out;
5387 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005388
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005389 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005390
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005391 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005392 if (port1 != port2) {
5393 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5394 file, linenum, args[0], args[1]);
5395 err_code |= ERR_ALERT | ERR_FATAL;
5396 goto out;
5397 }
5398
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005399 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005400 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005401 }
William Lallemand0f99e342011-10-12 17:50:54 +02005402
5403 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005404 }
5405 else {
5406 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5407 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005408 err_code |= ERR_ALERT | ERR_FATAL;
5409 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005410 }
5411 }
5412 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005413 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005414 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005415 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005416 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005417
Willy Tarreau977b8e42006-12-29 14:19:17 +01005418 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005419 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005420
Willy Tarreaubaaee002006-06-26 02:48:02 +02005421 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005422 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5423 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005424 err_code |= ERR_ALERT | ERR_FATAL;
5425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005426 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005427
5428 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005429 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5430 free(curproxy->conn_src.iface_name);
5431 curproxy->conn_src.iface_name = NULL;
5432 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005433
Willy Tarreau902636f2013-03-10 19:44:48 +01005434 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005435 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005436 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005437 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005438 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005439 goto out;
5440 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005441
5442 proto = protocol_by_family(sk->ss_family);
5443 if (!proto || !proto->connect) {
5444 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005445 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005446 err_code |= ERR_ALERT | ERR_FATAL;
5447 goto out;
5448 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005449
5450 if (port1 != port2) {
5451 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5452 file, linenum, args[0], args[1]);
5453 err_code |= ERR_ALERT | ERR_FATAL;
5454 goto out;
5455 }
5456
Willy Tarreauef9a3602012-12-08 22:29:20 +01005457 curproxy->conn_src.source_addr = *sk;
5458 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005459
5460 cur_arg = 2;
5461 while (*(args[cur_arg])) {
5462 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005463#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5464#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005465 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005466 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5467 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005468 err_code |= ERR_ALERT | ERR_FATAL;
5469 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005470 }
5471#endif
5472 if (!*args[cur_arg + 1]) {
5473 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5474 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005475 err_code |= ERR_ALERT | ERR_FATAL;
5476 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005477 }
5478
5479 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005480 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5481 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005482 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005483 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5484 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005485 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5486 char *name, *end;
5487
5488 name = args[cur_arg+1] + 7;
5489 while (isspace(*name))
5490 name++;
5491
5492 end = name;
5493 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5494 end++;
5495
Willy Tarreauef9a3602012-12-08 22:29:20 +01005496 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5497 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5498 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5499 curproxy->conn_src.bind_hdr_len = end - name;
5500 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5501 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5502 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005503
5504 /* now look for an occurrence number */
5505 while (isspace(*end))
5506 end++;
5507 if (*end == ',') {
5508 end++;
5509 name = end;
5510 if (*end == '-')
5511 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005512 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005513 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005514 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005515 }
5516
Willy Tarreauef9a3602012-12-08 22:29:20 +01005517 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005518 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5519 " occurrences values smaller than %d.\n",
5520 file, linenum, MAX_HDR_HISTORY);
5521 err_code |= ERR_ALERT | ERR_FATAL;
5522 goto out;
5523 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005524 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005525 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005526
Willy Tarreau902636f2013-03-10 19:44:48 +01005527 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005528 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005529 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005530 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005531 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005532 goto out;
5533 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005534
5535 proto = protocol_by_family(sk->ss_family);
5536 if (!proto || !proto->connect) {
5537 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5538 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005539 err_code |= ERR_ALERT | ERR_FATAL;
5540 goto out;
5541 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005542
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005543 if (port1 != port2) {
5544 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5545 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005546 err_code |= ERR_ALERT | ERR_FATAL;
5547 goto out;
5548 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005549 curproxy->conn_src.tproxy_addr = *sk;
5550 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005551 }
5552 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005553#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005554 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005555#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005556#else /* no TPROXY support */
5557 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005558 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005559 err_code |= ERR_ALERT | ERR_FATAL;
5560 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005561#endif
5562 cur_arg += 2;
5563 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005564 }
5565
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005566 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5567#ifdef SO_BINDTODEVICE
5568 if (!*args[cur_arg + 1]) {
5569 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5570 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005571 err_code |= ERR_ALERT | ERR_FATAL;
5572 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005573 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005574 free(curproxy->conn_src.iface_name);
5575 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5576 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005577 global.last_checks |= LSTCHK_NETADM;
5578#else
5579 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5580 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005581 err_code |= ERR_ALERT | ERR_FATAL;
5582 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005583#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005584 cur_arg += 2;
5585 continue;
5586 }
5587 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005588 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005589 err_code |= ERR_ALERT | ERR_FATAL;
5590 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005591 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005592 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005593 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5594 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5595 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005596 err_code |= ERR_ALERT | ERR_FATAL;
5597 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005598 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005599 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005600 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005601 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5602 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005603 err_code |= ERR_ALERT | ERR_FATAL;
5604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005606
5607 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005608 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005609 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005610 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005612 }
5613 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005614 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005615 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005616 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005617 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005619 }
5620 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005621 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005622 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005623 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005624 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005626 }
5627 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005628 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005629 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005630 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005631 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005633 }
5634 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005635 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005636 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005637 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005638 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005640 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005641 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005642 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005643 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005644 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005645 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005646 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005647 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005648 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005649 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005650 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005651 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005652 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005653 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005654
5655 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5656 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of the more efficient 'use_backend' which uses a different but more powerful syntax. Future versions will not support '%s' anymore, you should convert it now!\n", file, linenum, args[0], args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01005657 }
5658 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005659 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005660 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005661 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005662 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005663 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005664
5665 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5666 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of the more efficient 'use_backend' which uses a different but more powerful syntax. Future versions will not support '%s' anymore, you should convert it now!\n", file, linenum, args[0], args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01005667 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005668 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005669 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005670 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5671 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005672 err_code |= ERR_ALERT | ERR_FATAL;
5673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005674 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005675
5676 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005677 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005678 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005679 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005680 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005681 }
5682 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005683 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005684 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005685 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005686 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005688 }
5689 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005690 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005691 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005692 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005693 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005694 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005695 }
5696 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005697 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005698 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005699 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005700 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005702 }
5703 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005704 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005705 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005706 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005707 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005708 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005709 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005710 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005711 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005712 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005713 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005714 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005715 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005716 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005717 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005718 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005719
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720 if (curproxy == &defproxy) {
5721 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005722 err_code |= ERR_ALERT | ERR_FATAL;
5723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005725 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005726 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005727
Willy Tarreaubaaee002006-06-26 02:48:02 +02005728 if (*(args[1]) == 0) {
5729 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005730 err_code |= ERR_ALERT | ERR_FATAL;
5731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005732 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005733
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005734 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005735 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5736 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5737 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005738 err_code |= ERR_ALERT | ERR_FATAL;
5739 goto out;
5740 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005741 err_code |= warnif_cond_conflicts(cond,
5742 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5743 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005744 }
5745 else if (*args[2]) {
5746 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5747 file, linenum, args[0], args[2]);
5748 err_code |= ERR_ALERT | ERR_FATAL;
5749 goto out;
5750 }
5751
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005752 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005753 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005754 wl->s = strdup(args[1]);
5755 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005756 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005757 }
5758 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005759 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005760 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5761 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005762 err_code |= ERR_ALERT | ERR_FATAL;
5763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005764 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005765
Willy Tarreauade5ec42010-01-28 19:33:49 +01005766 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005767 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005768 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005769 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771 }
5772 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005773 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005774 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005775 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005776 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005778 }
5779 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005780 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005781 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005782 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005783 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005785 }
5786 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005787 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5789 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005790 err_code |= ERR_ALERT | ERR_FATAL;
5791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792 }
5793
Willy Tarreauade5ec42010-01-28 19:33:49 +01005794 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005795 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005796 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005797 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005799 }
5800 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005801 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005802 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005803 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005804 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005806 }
5807 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005808 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005809 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005810 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005811 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005813 }
5814 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005815 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005816
Willy Tarreaubaaee002006-06-26 02:48:02 +02005817 if (curproxy == &defproxy) {
5818 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005819 err_code |= ERR_ALERT | ERR_FATAL;
5820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005821 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005822 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005823 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005824
Willy Tarreaubaaee002006-06-26 02:48:02 +02005825 if (*(args[1]) == 0) {
5826 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005827 err_code |= ERR_ALERT | ERR_FATAL;
5828 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005829 }
5830
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005831 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005832 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5833 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5834 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005835 err_code |= ERR_ALERT | ERR_FATAL;
5836 goto out;
5837 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005838 err_code |= warnif_cond_conflicts(cond,
5839 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5840 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005841 }
5842 else if (*args[2]) {
5843 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5844 file, linenum, args[0], args[2]);
5845 err_code |= ERR_ALERT | ERR_FATAL;
5846 goto out;
5847 }
5848
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005849 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005850 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005851 wl->s = strdup(args[1]);
5852 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005853 }
5854 else if (!strcmp(args[0], "errorloc") ||
5855 !strcmp(args[0], "errorloc302") ||
5856 !strcmp(args[0], "errorloc303")) { /* error location */
5857 int errnum, errlen;
5858 char *err;
5859
Willy Tarreau977b8e42006-12-29 14:19:17 +01005860 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005861 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005862
Willy Tarreaubaaee002006-06-26 02:48:02 +02005863 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005864 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005865 err_code |= ERR_ALERT | ERR_FATAL;
5866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005867 }
5868
5869 errnum = atol(args[1]);
5870 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005871 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5872 err = malloc(errlen);
5873 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005874 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005875 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5876 err = malloc(errlen);
5877 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005878 }
5879
Willy Tarreau0f772532006-12-23 20:51:41 +01005880 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5881 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005882 chunk_destroy(&curproxy->errmsg[rc]);
5883 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005884 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005885 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005886 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005887
5888 if (rc >= HTTP_ERR_SIZE) {
5889 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5890 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 free(err);
5892 }
5893 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005894 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5895 int errnum, errlen, fd;
5896 char *err;
5897 struct stat stat;
5898
5899 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005900 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005901
5902 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005903 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005904 err_code |= ERR_ALERT | ERR_FATAL;
5905 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005906 }
5907
5908 fd = open(args[2], O_RDONLY);
5909 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5910 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5911 file, linenum, args[2], args[1]);
5912 if (fd >= 0)
5913 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005914 err_code |= ERR_ALERT | ERR_FATAL;
5915 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005916 }
5917
Willy Tarreau27a674e2009-08-17 07:23:33 +02005918 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005919 errlen = stat.st_size;
5920 } else {
5921 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005922 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005923 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005924 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005925 }
5926
5927 err = malloc(errlen); /* malloc() must succeed during parsing */
5928 errnum = read(fd, err, errlen);
5929 if (errnum != errlen) {
5930 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5931 file, linenum, args[2], args[1]);
5932 close(fd);
5933 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005934 err_code |= ERR_ALERT | ERR_FATAL;
5935 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005936 }
5937 close(fd);
5938
5939 errnum = atol(args[1]);
5940 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5941 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005942 chunk_destroy(&curproxy->errmsg[rc]);
5943 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005944 break;
5945 }
5946 }
5947
5948 if (rc >= HTTP_ERR_SIZE) {
5949 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5950 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005951 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005952 free(err);
5953 }
5954 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005955 else if (!strcmp(args[0], "compression")) {
5956 struct comp *comp;
5957 if (curproxy->comp == NULL) {
5958 comp = calloc(1, sizeof(struct comp));
5959 curproxy->comp = comp;
5960 } else {
5961 comp = curproxy->comp;
5962 }
5963
5964 if (!strcmp(args[1], "algo")) {
5965 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005966 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005967
William Lallemand82fe75c2012-10-23 10:25:10 +02005968 cur_arg = 2;
5969 if (!*args[cur_arg]) {
5970 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5971 file, linenum, args[0]);
5972 err_code |= ERR_ALERT | ERR_FATAL;
5973 goto out;
5974 }
5975 while (*(args[cur_arg])) {
5976 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5977 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5978 file, linenum, args[0], args[cur_arg]);
5979 err_code |= ERR_ALERT | ERR_FATAL;
5980 goto out;
5981 }
William Lallemand552df672012-11-07 13:21:47 +01005982 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5983 curproxy->comp->algos->end(&ctx);
5984 } else {
5985 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5986 file, linenum, args[0], args[cur_arg]);
5987 err_code |= ERR_ALERT | ERR_FATAL;
5988 goto out;
5989 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005990 cur_arg ++;
5991 continue;
5992 }
5993 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005994 else if (!strcmp(args[1], "offload")) {
5995 comp->offload = 1;
5996 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005997 else if (!strcmp(args[1], "type")) {
5998 int cur_arg;
5999 cur_arg = 2;
6000 if (!*args[cur_arg]) {
6001 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6002 file, linenum, args[0]);
6003 err_code |= ERR_ALERT | ERR_FATAL;
6004 goto out;
6005 }
6006 while (*(args[cur_arg])) {
6007 comp_append_type(comp, args[cur_arg]);
6008 cur_arg ++;
6009 continue;
6010 }
6011 }
6012 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006013 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006014 file, linenum, args[0]);
6015 err_code |= ERR_ALERT | ERR_FATAL;
6016 goto out;
6017 }
6018 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006019 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006020 struct cfg_kw_list *kwl;
6021 int index;
6022
6023 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6024 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6025 if (kwl->kw[index].section != CFG_LISTEN)
6026 continue;
6027 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6028 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006029 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006030 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006031 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006032 err_code |= ERR_ALERT | ERR_FATAL;
6033 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006034 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006035 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006036 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006037 err_code |= ERR_WARN;
6038 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006039 }
Willy Tarreau93893792009-07-23 13:19:11 +02006040 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006041 }
6042 }
6043 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006044
Willy Tarreau6daf3432008-01-22 16:44:08 +01006045 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006046 err_code |= ERR_ALERT | ERR_FATAL;
6047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006048 }
Willy Tarreau93893792009-07-23 13:19:11 +02006049 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006050 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006051 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006052}
6053
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006054int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006055cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6056{
6057#ifdef CONFIG_HAP_NS
6058 const char *err;
6059 const char *item = args[0];
6060
6061 if (!strcmp(item, "namespace_list")) {
6062 return 0;
6063 }
6064 else if (!strcmp(item, "namespace")) {
6065 size_t idx = 1;
6066 const char *current;
6067 while (*(current = args[idx++])) {
6068 err = invalid_char(current);
6069 if (err) {
6070 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6071 file, linenum, *err, item, current);
6072 return ERR_ALERT | ERR_FATAL;
6073 }
6074
6075 if (netns_store_lookup(current, strlen(current))) {
6076 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6077 file, linenum, current);
6078 return ERR_ALERT | ERR_FATAL;
6079 }
6080 if (!netns_store_insert(current)) {
6081 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6082 file, linenum, current);
6083 return ERR_ALERT | ERR_FATAL;
6084 }
6085 }
6086 }
6087
6088 return 0;
6089#else
6090 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6091 file, linenum);
6092 return ERR_ALERT | ERR_FATAL;
6093#endif
6094}
6095
6096int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006097cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6098{
6099
6100 int err_code = 0;
6101 const char *err;
6102
6103 if (!strcmp(args[0], "userlist")) { /* new userlist */
6104 struct userlist *newul;
6105
6106 if (!*args[1]) {
6107 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6108 file, linenum, args[0]);
6109 err_code |= ERR_ALERT | ERR_FATAL;
6110 goto out;
6111 }
6112
6113 err = invalid_char(args[1]);
6114 if (err) {
6115 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6116 file, linenum, *err, args[0], args[1]);
6117 err_code |= ERR_ALERT | ERR_FATAL;
6118 goto out;
6119 }
6120
6121 for (newul = userlist; newul; newul = newul->next)
6122 if (!strcmp(newul->name, args[1])) {
6123 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6124 file, linenum, args[1]);
6125 err_code |= ERR_WARN;
6126 goto out;
6127 }
6128
6129 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6130 if (!newul) {
6131 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6132 err_code |= ERR_ALERT | ERR_ABORT;
6133 goto out;
6134 }
6135
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006136 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006137 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006138 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6139 err_code |= ERR_ALERT | ERR_ABORT;
6140 goto out;
6141 }
6142
6143 newul->next = userlist;
6144 userlist = newul;
6145
6146 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006147 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006148 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006149 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006150
6151 if (!*args[1]) {
6152 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6153 file, linenum, args[0]);
6154 err_code |= ERR_ALERT | ERR_FATAL;
6155 goto out;
6156 }
6157
6158 err = invalid_char(args[1]);
6159 if (err) {
6160 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6161 file, linenum, *err, args[0], args[1]);
6162 err_code |= ERR_ALERT | ERR_FATAL;
6163 goto out;
6164 }
6165
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006166 for (ag = userlist->groups; ag; ag = ag->next)
6167 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006168 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6169 file, linenum, args[1], userlist->name);
6170 err_code |= ERR_ALERT;
6171 goto out;
6172 }
6173
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006174 ag = calloc(1, sizeof(*ag));
6175 if (!ag) {
6176 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6177 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006178 goto out;
6179 }
6180
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006181 ag->name = strdup(args[1]);
6182 if (!ag) {
6183 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6184 err_code |= ERR_ALERT | ERR_ABORT;
6185 goto out;
6186 }
6187
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006188 cur_arg = 2;
6189
6190 while (*args[cur_arg]) {
6191 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006192 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006193 cur_arg += 2;
6194 continue;
6195 } else {
6196 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6197 file, linenum, args[0]);
6198 err_code |= ERR_ALERT | ERR_FATAL;
6199 goto out;
6200 }
6201 }
6202
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006203 ag->next = userlist->groups;
6204 userlist->groups = ag;
6205
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006206 } else if (!strcmp(args[0], "user")) { /* new user */
6207 struct auth_users *newuser;
6208 int cur_arg;
6209
6210 if (!*args[1]) {
6211 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6212 file, linenum, args[0]);
6213 err_code |= ERR_ALERT | ERR_FATAL;
6214 goto out;
6215 }
6216
6217 for (newuser = userlist->users; newuser; newuser = newuser->next)
6218 if (!strcmp(newuser->user, args[1])) {
6219 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6220 file, linenum, args[1], userlist->name);
6221 err_code |= ERR_ALERT;
6222 goto out;
6223 }
6224
6225 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6226 if (!newuser) {
6227 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6228 err_code |= ERR_ALERT | ERR_ABORT;
6229 goto out;
6230 }
6231
6232 newuser->user = strdup(args[1]);
6233
6234 newuser->next = userlist->users;
6235 userlist->users = newuser;
6236
6237 cur_arg = 2;
6238
6239 while (*args[cur_arg]) {
6240 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006241#ifdef CONFIG_HAP_CRYPT
6242 if (!crypt("", args[cur_arg + 1])) {
6243 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6244 file, linenum, newuser->user);
6245 err_code |= ERR_ALERT | ERR_FATAL;
6246 goto out;
6247 }
6248#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006249 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6250 file, linenum);
6251 err_code |= ERR_ALERT;
6252#endif
6253 newuser->pass = strdup(args[cur_arg + 1]);
6254 cur_arg += 2;
6255 continue;
6256 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6257 newuser->pass = strdup(args[cur_arg + 1]);
6258 newuser->flags |= AU_O_INSECURE;
6259 cur_arg += 2;
6260 continue;
6261 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006262 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006263 cur_arg += 2;
6264 continue;
6265 } else {
6266 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6267 file, linenum, args[0]);
6268 err_code |= ERR_ALERT | ERR_FATAL;
6269 goto out;
6270 }
6271 }
6272 } else {
6273 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6274 err_code |= ERR_ALERT | ERR_FATAL;
6275 }
6276
6277out:
6278 return err_code;
6279}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006280
6281/*
6282 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006283 * Returns the error code, 0 if OK, or any combination of :
6284 * - ERR_ABORT: must abort ASAP
6285 * - ERR_FATAL: we can continue parsing but not start the service
6286 * - ERR_WARN: a warning has been emitted
6287 * - ERR_ALERT: an alert has been emitted
6288 * Only the two first ones can stop processing, the two others are just
6289 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006290 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006291int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006292{
William Lallemand64e84512015-05-12 14:25:37 +02006293 char *thisline;
6294 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006295 FILE *f;
6296 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006297 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006298 struct cfg_section *cs = NULL;
6299 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006300 int readbytes = 0;
6301
6302 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006303 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006304 return -1;
6305 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006306
6307 /* Register internal sections */
6308 if (!cfg_register_section("listen", cfg_parse_listen) ||
6309 !cfg_register_section("frontend", cfg_parse_listen) ||
6310 !cfg_register_section("backend", cfg_parse_listen) ||
6311 !cfg_register_section("ruleset", cfg_parse_listen) ||
6312 !cfg_register_section("defaults", cfg_parse_listen) ||
6313 !cfg_register_section("global", cfg_parse_global) ||
6314 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006315 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006316 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006317 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006318 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006319
Willy Tarreaubaaee002006-06-26 02:48:02 +02006320 if ((f=fopen(file,"r")) == NULL)
6321 return -1;
6322
William Lallemandb2f07452015-05-12 14:27:13 +02006323next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006324 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006325 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006326 char *end;
6327 char *args[MAX_LINE_ARGS + 1];
6328 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006329 int dquote = 0; /* double quote */
6330 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006331
Willy Tarreaubaaee002006-06-26 02:48:02 +02006332 linenum++;
6333
6334 end = line + strlen(line);
6335
William Lallemand64e84512015-05-12 14:25:37 +02006336 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006337 /* Check if we reached the limit and the last char is not \n.
6338 * Watch out for the last line without the terminating '\n'!
6339 */
William Lallemand64e84512015-05-12 14:25:37 +02006340 char *newline;
6341 int newlinesize = linesize * 2;
6342
6343 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6344 if (newline == NULL) {
6345 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6346 file, linenum);
6347 err_code |= ERR_ALERT | ERR_FATAL;
6348 continue;
6349 }
6350
6351 readbytes = linesize - 1;
6352 linesize = newlinesize;
6353 thisline = newline;
6354 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006355 }
6356
William Lallemand64e84512015-05-12 14:25:37 +02006357 readbytes = 0;
6358
Willy Tarreaubaaee002006-06-26 02:48:02 +02006359 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006360 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006361 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006362
Willy Tarreaubaaee002006-06-26 02:48:02 +02006363 arg = 0;
6364 args[arg] = line;
6365
6366 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006367 if (*line == '"' && !squote) { /* double quote outside single quotes */
6368 if (dquote)
6369 dquote = 0;
6370 else
6371 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006372 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006373 end--;
6374 }
6375 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6376 if (squote)
6377 squote = 0;
6378 else
6379 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006380 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006381 end--;
6382 }
6383 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006384 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6385 * C equivalent value. Other combinations left unchanged (eg: \1).
6386 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006387 int skip = 0;
6388 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6389 *line = line[1];
6390 skip = 1;
6391 }
6392 else if (line[1] == 'r') {
6393 *line = '\r';
6394 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006395 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006396 else if (line[1] == 'n') {
6397 *line = '\n';
6398 skip = 1;
6399 }
6400 else if (line[1] == 't') {
6401 *line = '\t';
6402 skip = 1;
6403 }
6404 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006405 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006406 unsigned char hex1, hex2;
6407 hex1 = toupper(line[2]) - '0';
6408 hex2 = toupper(line[3]) - '0';
6409 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6410 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6411 *line = (hex1<<4) + hex2;
6412 skip = 3;
6413 }
6414 else {
6415 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006416 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006417 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006418 } else if (line[1] == '"') {
6419 *line = '"';
6420 skip = 1;
6421 } else if (line[1] == '\'') {
6422 *line = '\'';
6423 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006424 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6425 *line = '$';
6426 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006427 }
6428 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006429 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006430 end -= skip;
6431 }
6432 line++;
6433 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006434 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006435 /* end of string, end of loop */
6436 *line = 0;
6437 break;
6438 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006439 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006440 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006441 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006442 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006443 line++;
6444 args[++arg] = line;
6445 }
William Lallemandb2f07452015-05-12 14:27:13 +02006446 else if (dquote && *line == '$') {
6447 /* environment variables are evaluated inside double quotes */
6448 char *var_beg;
6449 char *var_end;
6450 char save_char;
6451 char *value;
6452 int val_len;
6453 int newlinesize;
6454 int braces = 0;
6455
6456 var_beg = line + 1;
6457 var_end = var_beg;
6458
6459 if (*var_beg == '{') {
6460 var_beg++;
6461 var_end++;
6462 braces = 1;
6463 }
6464
6465 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6466 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6467 err_code |= ERR_ALERT | ERR_FATAL;
6468 goto next_line; /* skip current line */
6469 }
6470
6471 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6472 var_end++;
6473
6474 save_char = *var_end;
6475 *var_end = '\0';
6476 value = getenv(var_beg);
6477 *var_end = save_char;
6478 val_len = value ? strlen(value) : 0;
6479
6480 if (braces) {
6481 if (*var_end == '}') {
6482 var_end++;
6483 braces = 0;
6484 } else {
6485 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
6486 err_code |= ERR_ALERT | ERR_FATAL;
6487 goto next_line; /* skip current line */
6488 }
6489 }
6490
6491 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
6492
6493 /* if not enough space in thisline */
6494 if (newlinesize > linesize) {
6495 char *newline;
6496
6497 newline = realloc(thisline, newlinesize * sizeof(*thisline));
6498 if (newline == NULL) {
6499 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
6500 err_code |= ERR_ALERT | ERR_FATAL;
6501 goto next_line; /* slip current line */
6502 }
6503 /* recompute pointers if realloc returns a new pointer */
6504 if (newline != thisline) {
6505 int i;
6506 int diff;
6507
6508 for (i = 0; i <= arg; i++) {
6509 diff = args[i] - thisline;
6510 args[i] = newline + diff;
6511 }
6512
6513 diff = var_end - thisline;
6514 var_end = newline + diff;
6515 diff = end - thisline;
6516 end = newline + diff;
6517 diff = line - thisline;
6518 line = newline + diff;
6519 thisline = newline;
6520 }
6521 linesize = newlinesize;
6522 }
6523
6524 /* insert value inside the line */
6525 memmove(line + val_len, var_end, end - var_end + 1);
6526 memcpy(line, value, val_len);
6527 end += val_len - (var_end - line);
6528 line += val_len;
6529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006530 else {
6531 line++;
6532 }
6533 }
William Lallemandb2f07452015-05-12 14:27:13 +02006534
William Lallemandf9873ba2015-05-05 17:37:14 +02006535 if (dquote) {
6536 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
6537 err_code |= ERR_ALERT | ERR_FATAL;
6538 }
6539
6540 if (squote) {
6541 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
6542 err_code |= ERR_ALERT | ERR_FATAL;
6543 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006544
6545 /* empty line */
6546 if (!**args)
6547 continue;
6548
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006549 if (*line) {
6550 /* we had to stop due to too many args.
6551 * Let's terminate the string, print the offending part then cut the
6552 * last arg.
6553 */
6554 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6555 line++;
6556 *line = '\0';
6557
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006558 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006559 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006560 err_code |= ERR_ALERT | ERR_FATAL;
6561 args[arg] = line;
6562 }
6563
Willy Tarreau540abe42007-05-02 20:50:16 +02006564 /* zero out remaining args and ensure that at least one entry
6565 * is zeroed out.
6566 */
6567 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006568 args[arg] = line;
6569 }
6570
Willy Tarreau3842f002009-06-14 11:39:52 +02006571 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006572 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006573 char *tmp;
6574
Willy Tarreau3842f002009-06-14 11:39:52 +02006575 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006576 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006577 for (arg=0; *args[arg+1]; arg++)
6578 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006579 *tmp = '\0'; // fix the next arg to \0
6580 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006581 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006582 else if (!strcmp(args[0], "default")) {
6583 kwm = KWM_DEF;
6584 for (arg=0; *args[arg+1]; arg++)
6585 args[arg] = args[arg+1]; // shift args after inversion
6586 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006587
William Lallemand0f99e342011-10-12 17:50:54 +02006588 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6589 strcmp(args[0], "log") != 0) {
6590 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006591 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006592 }
6593
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006594 /* detect section start */
6595 list_for_each_entry(ics, &sections, list) {
6596 if (strcmp(args[0], ics->section_name) == 0) {
6597 cursection = ics->section_name;
6598 cs = ics;
6599 break;
6600 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006601 }
6602
Willy Tarreaubaaee002006-06-26 02:48:02 +02006603 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006604 if (cs)
6605 err_code |= cs->section_parser(file, linenum, args, kwm);
6606 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006607 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006608 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006609 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006610
6611 if (err_code & ERR_ABORT)
6612 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006613 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006614 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02006615 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006616 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006617 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006618}
6619
Willy Tarreau64ab6072014-09-16 12:17:36 +02006620/* This function propagates processes from frontend <from> to backend <to> so
6621 * that it is always guaranteed that a backend pointed to by a frontend is
6622 * bound to all of its processes. After that, if the target is a "listen"
6623 * instance, the function recursively descends the target's own targets along
6624 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6625 * checked first to ensure that <to> is already bound to all processes of
6626 * <from>, there is no risk of looping and we ensure to follow the shortest
6627 * path to the destination.
6628 *
6629 * It is possible to set <to> to NULL for the first call so that the function
6630 * takes care of visiting the initial frontend in <from>.
6631 *
6632 * It is important to note that the function relies on the fact that all names
6633 * have already been resolved.
6634 */
6635void propagate_processes(struct proxy *from, struct proxy *to)
6636{
6637 struct switching_rule *rule;
6638 struct hdr_exp *exp;
6639
6640 if (to) {
6641 /* check whether we need to go down */
6642 if (from->bind_proc &&
6643 (from->bind_proc & to->bind_proc) == from->bind_proc)
6644 return;
6645
6646 if (!from->bind_proc && !to->bind_proc)
6647 return;
6648
6649 to->bind_proc = from->bind_proc ?
6650 (to->bind_proc | from->bind_proc) : 0;
6651
6652 /* now propagate down */
6653 from = to;
6654 }
6655
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006656 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006657 return;
6658
Willy Tarreauf6b70012014-12-18 14:00:43 +01006659 if (from->state == PR_STSTOPPED)
6660 return;
6661
Willy Tarreau64ab6072014-09-16 12:17:36 +02006662 /* default_backend */
6663 if (from->defbe.be)
6664 propagate_processes(from, from->defbe.be);
6665
6666 /* use_backend */
6667 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006668 if (rule->dynamic)
6669 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006670 to = rule->be.backend;
6671 propagate_processes(from, to);
6672 }
6673
6674 /* reqsetbe */
6675 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6676 if (exp->action != ACT_SETBE)
6677 continue;
6678 to = (struct proxy *)exp->replace;
6679 propagate_processes(from, to);
6680 }
6681}
6682
Willy Tarreaubb925012009-07-23 13:36:36 +02006683/*
6684 * Returns the error code, 0 if OK, or any combination of :
6685 * - ERR_ABORT: must abort ASAP
6686 * - ERR_FATAL: we can continue parsing but not start the service
6687 * - ERR_WARN: a warning has been emitted
6688 * - ERR_ALERT: an alert has been emitted
6689 * Only the two first ones can stop processing, the two others are just
6690 * indicators.
6691 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006692int check_config_validity()
6693{
6694 int cfgerr = 0;
6695 struct proxy *curproxy = NULL;
6696 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006697 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006698 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006699 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006700
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006701 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006702 /*
6703 * Now, check for the integrity of all that we have collected.
6704 */
6705
6706 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006707 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006708
Willy Tarreau193b8c62012-11-22 00:17:38 +01006709 if (!global.tune.max_http_hdr)
6710 global.tune.max_http_hdr = MAX_HTTP_HDR;
6711
6712 if (!global.tune.cookie_len)
6713 global.tune.cookie_len = CAPTURE_LEN;
6714
6715 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6716
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006717 /* Post initialisation of the users and groups lists. */
6718 err_code = userlist_postinit();
6719 if (err_code != ERR_NONE)
6720 goto out;
6721
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006722 /* first, we will invert the proxy list order */
6723 curproxy = NULL;
6724 while (proxy) {
6725 struct proxy *next;
6726
6727 next = proxy->next;
6728 proxy->next = curproxy;
6729 curproxy = proxy;
6730 if (!next)
6731 break;
6732 proxy = next;
6733 }
6734
Willy Tarreau419ead82014-09-16 13:41:21 +02006735 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006736 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006737 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006738 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006739 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006740 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006741 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006742 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006743
Willy Tarreau050536d2012-10-04 08:47:34 +02006744 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006745 /* proxy ID not set, use automatic numbering with first
6746 * spare entry starting with next_pxid.
6747 */
6748 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6749 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6750 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006751 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006752 next_pxid++;
6753
Willy Tarreau55ea7572007-06-17 19:56:27 +02006754
Willy Tarreaubaaee002006-06-26 02:48:02 +02006755 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006756 /* ensure we don't keep listeners uselessly bound */
6757 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02006758 free((void *)curproxy->table.peers.name);
6759 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006760 continue;
6761 }
6762
Willy Tarreau102df612014-05-07 23:56:38 +02006763 /* Check multi-process mode compatibility for the current proxy */
6764
6765 if (curproxy->bind_proc) {
6766 /* an explicit bind-process was specified, let's check how many
6767 * processes remain.
6768 */
6769 nbproc = popcount(curproxy->bind_proc);
6770
6771 curproxy->bind_proc &= nbits(global.nbproc);
6772 if (!curproxy->bind_proc && nbproc == 1) {
6773 Warning("Proxy '%s': the process specified on the 'bind-process' directive refers to a process number that is higher than global.nbproc. The proxy has been forced to run on process 1 only.\n", curproxy->id);
6774 curproxy->bind_proc = 1;
6775 }
6776 else if (!curproxy->bind_proc && nbproc > 1) {
6777 Warning("Proxy '%s': all processes specified on the 'bind-process' directive refer to numbers that are all higher than global.nbproc. The directive was ignored and the proxy will run on all processes.\n", curproxy->id);
6778 curproxy->bind_proc = 0;
6779 }
6780 }
6781
Willy Tarreau3d209582014-05-09 17:06:11 +02006782 /* check and reduce the bind-proc of each listener */
6783 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6784 unsigned long mask;
6785
6786 if (!bind_conf->bind_proc)
6787 continue;
6788
6789 mask = nbits(global.nbproc);
6790 if (curproxy->bind_proc)
6791 mask &= curproxy->bind_proc;
6792 /* mask cannot be null here thanks to the previous checks */
6793
6794 nbproc = popcount(bind_conf->bind_proc);
6795 bind_conf->bind_proc &= mask;
6796
6797 if (!bind_conf->bind_proc && nbproc == 1) {
6798 Warning("Proxy '%s': the process number specified on the 'process' directive of 'bind %s' at [%s:%d] refers to a process not covered by the proxy. This has been fixed by forcing it to run on the proxy's first process only.\n",
6799 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6800 bind_conf->bind_proc = mask & ~(mask - 1);
6801 }
6802 else if (!bind_conf->bind_proc && nbproc > 1) {
6803 Warning("Proxy '%s': the process range specified on the 'process' directive of 'bind %s' at [%s:%d] only refers to processes not covered by the proxy. The directive was ignored so that all of the proxy's processes are used.\n",
6804 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6805 bind_conf->bind_proc = 0;
6806 }
6807 }
6808
Willy Tarreauff01a212009-03-15 13:46:16 +01006809 switch (curproxy->mode) {
6810 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006811 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006812 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006813 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6814 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006815 cfgerr++;
6816 }
6817
6818 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006819 Warning("config : servers will be ignored for %s '%s'.\n",
6820 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006821 break;
6822
6823 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006824 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006825 break;
6826
6827 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006828 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006829 break;
6830 }
6831
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006832 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006833 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006834 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006835 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6836 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006837 cfgerr++;
6838 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006839#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006840 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006841 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6842 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006843 cfgerr++;
6844 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006845#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006846 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006847 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6848 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006849 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006850 }
6851 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006852 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006853 /* If no LB algo is set in a backend, and we're not in
6854 * transparent mode, dispatch mode nor proxy mode, we
6855 * want to use balance roundrobin by default.
6856 */
6857 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6858 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006859 }
6860 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006861
Willy Tarreau1620ec32011-08-06 17:05:02 +02006862 if (curproxy->options & PR_O_DISPATCH)
6863 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6864 else if (curproxy->options & PR_O_HTTP_PROXY)
6865 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6866 else if (curproxy->options & PR_O_TRANSP)
6867 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006868
Willy Tarreau1620ec32011-08-06 17:05:02 +02006869 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6870 if (curproxy->options & PR_O_DISABLE404) {
6871 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6872 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6873 err_code |= ERR_WARN;
6874 curproxy->options &= ~PR_O_DISABLE404;
6875 }
6876 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6877 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6878 "send-state", proxy_type_str(curproxy), curproxy->id);
6879 err_code |= ERR_WARN;
6880 curproxy->options &= ~PR_O2_CHK_SNDST;
6881 }
Willy Tarreauef781042010-01-27 11:53:01 +01006882 }
6883
Simon Horman98637e52014-06-20 12:30:16 +09006884 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6885 if (!global.external_check) {
6886 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6887 curproxy->id, "option external-check");
6888 cfgerr++;
6889 }
6890 if (!curproxy->check_command) {
6891 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6892 curproxy->id, "option external-check");
6893 cfgerr++;
6894 }
6895 }
6896
Simon Horman64e34162015-02-06 11:11:57 +09006897 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006898 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
6899 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09006900 "'email-alert from', 'email-alert level' 'email-alert mailer', "
6901 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006902 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
6903 "to be present).\n",
6904 proxy_type_str(curproxy), curproxy->id);
6905 err_code |= ERR_WARN;
6906 free_email_alert(curproxy);
6907 }
6908 if (!curproxy->email_alert.myhostname)
6909 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09006910 }
6911
Simon Horman98637e52014-06-20 12:30:16 +09006912 if (curproxy->check_command) {
6913 int clear = 0;
6914 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6915 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6916 "external-check command", proxy_type_str(curproxy), curproxy->id);
6917 err_code |= ERR_WARN;
6918 clear = 1;
6919 }
6920 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6921 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6922 curproxy->id, "external-check command");
6923 cfgerr++;
6924 }
6925 if (clear) {
6926 free(curproxy->check_command);
6927 curproxy->check_command = NULL;
6928 }
6929 }
6930
6931 if (curproxy->check_path) {
6932 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6933 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6934 "external-check path", proxy_type_str(curproxy), curproxy->id);
6935 err_code |= ERR_WARN;
6936 free(curproxy->check_path);
6937 curproxy->check_path = NULL;
6938 }
6939 }
6940
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006941 /* if a default backend was specified, let's find it */
6942 if (curproxy->defbe.name) {
6943 struct proxy *target;
6944
Willy Tarreauafb39922015-05-26 12:04:09 +02006945 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006946 if (!target) {
6947 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6948 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006949 cfgerr++;
6950 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006951 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6952 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006953 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02006954 } else if (target->mode != curproxy->mode &&
6955 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
6956
6957 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
6958 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
6959 curproxy->conf.file, curproxy->conf.line,
6960 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
6961 target->conf.file, target->conf.line);
6962 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006963 } else {
6964 free(curproxy->defbe.name);
6965 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006966
6967 /* Emit a warning if this proxy also has some servers */
6968 if (curproxy->srv) {
6969 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6970 curproxy->id);
6971 err_code |= ERR_WARN;
6972 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006973 }
6974 }
6975
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006976 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006977 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6978 /* map jump target for ACT_SETBE in req_rep chain */
6979 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006980 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006981 struct proxy *target;
6982
Willy Tarreaua496b602006-12-17 23:15:24 +01006983 if (exp->action != ACT_SETBE)
6984 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006985
Willy Tarreauafb39922015-05-26 12:04:09 +02006986 target = proxy_be_by_name(exp->replace);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006987 if (!target) {
6988 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6989 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006990 cfgerr++;
6991 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006992 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6993 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006994 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02006995 } else if (target->mode != PR_MODE_HTTP) {
6996 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'reqsetbe' rule (see 'mode').\n",
6997 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
6998 curproxy->conf.file, curproxy->conf.line,
6999 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7000 target->conf.file, target->conf.line);
7001 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01007002 } else {
7003 free((void *)exp->replace);
7004 exp->replace = (const char *)target;
7005 }
7006 }
7007 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02007008
7009 /* find the target proxy for 'use_backend' rules */
7010 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007011 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007012 struct logformat_node *node;
7013 char *pxname;
7014
7015 /* Try to parse the string as a log format expression. If the result
7016 * of the parsing is only one entry containing a simple string, then
7017 * it's a standard string corresponding to a static rule, thus the
7018 * parsing is cancelled and be.name is restored to be resolved.
7019 */
7020 pxname = rule->be.name;
7021 LIST_INIT(&rule->be.expr);
7022 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7023 curproxy->conf.args.file, curproxy->conf.args.line);
7024 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7025
7026 if (!LIST_ISEMPTY(&rule->be.expr)) {
7027 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7028 rule->dynamic = 1;
7029 free(pxname);
7030 continue;
7031 }
7032 /* simple string: free the expression and fall back to static rule */
7033 free(node->arg);
7034 free(node);
7035 }
7036
7037 rule->dynamic = 0;
7038 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007039
Willy Tarreauafb39922015-05-26 12:04:09 +02007040 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007041 if (!target) {
7042 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7043 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007044 cfgerr++;
7045 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007046 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7047 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007048 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007049 } else if (target->mode != curproxy->mode &&
7050 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7051
7052 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7053 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7054 curproxy->conf.file, curproxy->conf.line,
7055 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7056 target->conf.file, target->conf.line);
7057 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007058 } else {
7059 free((void *)rule->be.name);
7060 rule->be.backend = target;
7061 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007062 }
7063
Willy Tarreau64ab6072014-09-16 12:17:36 +02007064 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007065 list_for_each_entry(srule, &curproxy->server_rules, list) {
7066 struct server *target = findserver(curproxy, srule->srv.name);
7067
7068 if (!target) {
7069 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7070 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7071 cfgerr++;
7072 continue;
7073 }
7074 free((void *)srule->srv.name);
7075 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007076 }
7077
Emeric Brunb982a3d2010-01-04 15:45:53 +01007078 /* find the target table for 'stick' rules */
7079 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7080 struct proxy *target;
7081
Emeric Brun1d33b292010-01-04 15:47:17 +01007082 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7083 if (mrule->flags & STK_IS_STORE)
7084 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7085
Emeric Brunb982a3d2010-01-04 15:45:53 +01007086 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007087 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007088 else
7089 target = curproxy;
7090
7091 if (!target) {
7092 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7093 curproxy->id, mrule->table.name);
7094 cfgerr++;
7095 }
7096 else if (target->table.size == 0) {
7097 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7098 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7099 cfgerr++;
7100 }
Willy Tarreau12785782012-04-27 21:37:17 +02007101 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7102 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007103 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7104 cfgerr++;
7105 }
7106 else {
7107 free((void *)mrule->table.name);
7108 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007109 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007110 }
7111 }
7112
7113 /* find the target table for 'store response' rules */
7114 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7115 struct proxy *target;
7116
Emeric Brun1d33b292010-01-04 15:47:17 +01007117 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7118
Emeric Brunb982a3d2010-01-04 15:45:53 +01007119 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007120 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007121 else
7122 target = curproxy;
7123
7124 if (!target) {
7125 Alert("Proxy '%s': unable to find store table '%s'.\n",
7126 curproxy->id, mrule->table.name);
7127 cfgerr++;
7128 }
7129 else if (target->table.size == 0) {
7130 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7131 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7132 cfgerr++;
7133 }
Willy Tarreau12785782012-04-27 21:37:17 +02007134 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7135 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007136 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7137 cfgerr++;
7138 }
7139 else {
7140 free((void *)mrule->table.name);
7141 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007142 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007143 }
7144 }
7145
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007146 /* find the target table for 'tcp-request' layer 4 rules */
7147 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7148 struct proxy *target;
7149
Willy Tarreaub4c84932013-07-23 19:15:30 +02007150 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007151 continue;
7152
7153 if (trule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007154 target = proxy_tbl_by_name(trule->act_prm.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007155 else
7156 target = curproxy;
7157
7158 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007159 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7160 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007161 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007162 cfgerr++;
7163 }
7164 else if (target->table.size == 0) {
7165 Alert("Proxy '%s': table '%s' used but not configured.\n",
7166 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7167 cfgerr++;
7168 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007169 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7170 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7171 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 +01007172 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007173 cfgerr++;
7174 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007175 else {
7176 free(trule->act_prm.trk_ctr.table.n);
7177 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007178 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007179 * to pass a list of counters to track and allocate them right here using
7180 * stktable_alloc_data_type().
7181 */
7182 }
7183 }
7184
Willy Tarreaud1f96522010-08-03 19:34:32 +02007185 /* find the target table for 'tcp-request' layer 6 rules */
7186 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7187 struct proxy *target;
7188
Willy Tarreaub4c84932013-07-23 19:15:30 +02007189 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007190 continue;
7191
7192 if (trule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007193 target = proxy_tbl_by_name(trule->act_prm.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007194 else
7195 target = curproxy;
7196
7197 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007198 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7199 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007200 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007201 cfgerr++;
7202 }
7203 else if (target->table.size == 0) {
7204 Alert("Proxy '%s': table '%s' used but not configured.\n",
7205 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7206 cfgerr++;
7207 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007208 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7209 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7210 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 +01007211 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007212 cfgerr++;
7213 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007214 else {
7215 free(trule->act_prm.trk_ctr.table.n);
7216 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007217 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007218 * to pass a list of counters to track and allocate them right here using
7219 * stktable_alloc_data_type().
7220 */
7221 }
7222 }
7223
Willy Tarreau09448f72014-06-25 18:12:15 +02007224 /* find the target table for 'http-request' layer 7 rules */
7225 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7226 struct proxy *target;
7227
7228 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
7229 continue;
7230
7231 if (hrqrule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007232 target = proxy_tbl_by_name(hrqrule->act_prm.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007233 else
7234 target = curproxy;
7235
7236 if (!target) {
7237 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7238 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
7239 http_req_trk_idx(hrqrule->action));
7240 cfgerr++;
7241 }
7242 else if (target->table.size == 0) {
7243 Alert("Proxy '%s': table '%s' used but not configured.\n",
7244 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
7245 cfgerr++;
7246 }
7247 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
7248 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7249 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
7250 http_req_trk_idx(hrqrule->action));
7251 cfgerr++;
7252 }
7253 else {
7254 free(hrqrule->act_prm.trk_ctr.table.n);
7255 hrqrule->act_prm.trk_ctr.table.t = &target->table;
7256 /* Note: if we decide to enhance the track-sc syntax, we may be able
7257 * to pass a list of counters to track and allocate them right here using
7258 * stktable_alloc_data_type().
7259 */
7260 }
7261 }
7262
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007263 /* move any "block" rules at the beginning of the http-request rules */
7264 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7265 /* insert block_rules into http_req_rules at the beginning */
7266 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7267 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7268 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7269 curproxy->http_req_rules.n = curproxy->block_rules.n;
7270 LIST_INIT(&curproxy->block_rules);
7271 }
7272
Emeric Brun32da3c42010-09-23 18:39:19 +02007273 if (curproxy->table.peers.name) {
7274 struct peers *curpeers = peers;
7275
7276 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7277 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7278 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007279 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007280 break;
7281 }
7282 }
7283
7284 if (!curpeers) {
7285 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7286 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007287 free((void *)curproxy->table.peers.name);
7288 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007289 cfgerr++;
7290 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007291 else if (curpeers->state == PR_STSTOPPED) {
7292 /* silently disable this peers section */
7293 curproxy->table.peers.p = NULL;
7294 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007295 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007296 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7297 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007298 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007299 cfgerr++;
7300 }
7301 }
7302
Simon Horman9dc49962015-01-30 11:22:59 +09007303
7304 if (curproxy->email_alert.mailers.name) {
7305 struct mailers *curmailers = mailers;
7306
7307 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7308 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7309 free(curproxy->email_alert.mailers.name);
7310 curproxy->email_alert.mailers.m = curmailers;
7311 curmailers->users++;
7312 break;
7313 }
7314 }
7315
7316 if (!curmailers) {
7317 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7318 curproxy->id, curproxy->email_alert.mailers.name);
7319 free_email_alert(curproxy);
7320 cfgerr++;
7321 }
7322 }
7323
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007324 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007325 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007326 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7327 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7328 "proxy", curproxy->id);
7329 cfgerr++;
7330 goto out_uri_auth_compat;
7331 }
7332
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007333 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007334 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007335 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007336 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007337
Willy Tarreau95fa4692010-02-01 13:05:50 +01007338 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7339 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007340
7341 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007342 uri_auth_compat_req[i++] = "realm";
7343 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7344 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007345
Willy Tarreau95fa4692010-02-01 13:05:50 +01007346 uri_auth_compat_req[i++] = "unless";
7347 uri_auth_compat_req[i++] = "{";
7348 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7349 uri_auth_compat_req[i++] = "}";
7350 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007351
Willy Tarreauff011f22011-01-06 17:51:27 +01007352 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7353 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007354 cfgerr++;
7355 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007356 }
7357
Willy Tarreauff011f22011-01-06 17:51:27 +01007358 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007359
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007360 if (curproxy->uri_auth->auth_realm) {
7361 free(curproxy->uri_auth->auth_realm);
7362 curproxy->uri_auth->auth_realm = NULL;
7363 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007364
7365 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007366 }
7367out_uri_auth_compat:
7368
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007369 /* compile the log format */
7370 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007371 if (curproxy->conf.logformat_string != default_http_log_format &&
7372 curproxy->conf.logformat_string != default_tcp_log_format &&
7373 curproxy->conf.logformat_string != clf_http_log_format)
7374 free(curproxy->conf.logformat_string);
7375 curproxy->conf.logformat_string = NULL;
7376 free(curproxy->conf.lfs_file);
7377 curproxy->conf.lfs_file = NULL;
7378 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007379 }
7380
Willy Tarreau62a61232013-04-12 18:13:46 +02007381 if (curproxy->conf.logformat_string) {
7382 curproxy->conf.args.ctx = ARGC_LOG;
7383 curproxy->conf.args.file = curproxy->conf.lfs_file;
7384 curproxy->conf.args.line = curproxy->conf.lfs_line;
7385 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007386 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007387 curproxy->conf.args.file = NULL;
7388 curproxy->conf.args.line = 0;
7389 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007390
Willy Tarreau62a61232013-04-12 18:13:46 +02007391 if (curproxy->conf.uniqueid_format_string) {
7392 curproxy->conf.args.ctx = ARGC_UIF;
7393 curproxy->conf.args.file = curproxy->conf.uif_file;
7394 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007395 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007396 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007397 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007398 curproxy->conf.args.file = NULL;
7399 curproxy->conf.args.line = 0;
7400 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007401
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007402 /* only now we can check if some args remain unresolved.
7403 * This must be done after the users and groups resolution.
7404 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007405 cfgerr += smp_resolve_args(curproxy);
7406 if (!cfgerr)
7407 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007408
Willy Tarreau2738a142006-07-08 17:28:09 +02007409 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007410 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007411 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007412 (!curproxy->timeout.connect ||
7413 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007414 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007415 " | While not properly invalid, you will certainly encounter various problems\n"
7416 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007417 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007418 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007419 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007420 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007421
Willy Tarreau1fa31262007-12-03 00:36:16 +01007422 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7423 * We must still support older configurations, so let's find out whether those
7424 * parameters have been set or must be copied from contimeouts.
7425 */
7426 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007427 if (!curproxy->timeout.tarpit ||
7428 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007429 /* tarpit timeout not set. We search in the following order:
7430 * default.tarpit, curr.connect, default.connect.
7431 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007432 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007433 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007434 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007435 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007436 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007437 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007438 }
7439 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007440 (!curproxy->timeout.queue ||
7441 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007442 /* queue timeout not set. We search in the following order:
7443 * default.queue, curr.connect, default.connect.
7444 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007445 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007446 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007447 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007448 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007449 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007450 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007451 }
7452 }
7453
Willy Tarreau1620ec32011-08-06 17:05:02 +02007454 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007455 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7456 curproxy->check_req = (char *)malloc(curproxy->check_len);
7457 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007458 }
7459
Willy Tarreau215663d2014-06-13 18:30:23 +02007460 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7461 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7462 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7463 proxy_type_str(curproxy), curproxy->id);
7464 err_code |= ERR_WARN;
7465 }
7466
Willy Tarreau193b8c62012-11-22 00:17:38 +01007467 /* ensure that cookie capture length is not too large */
7468 if (curproxy->capture_len >= global.tune.cookie_len) {
7469 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7470 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7471 err_code |= ERR_WARN;
7472 curproxy->capture_len = global.tune.cookie_len - 1;
7473 }
7474
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007475 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007476 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007477 curproxy->req_cap_pool = create_pool("ptrcap",
7478 curproxy->nb_req_cap * sizeof(char *),
7479 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007480 }
7481
7482 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007483 curproxy->rsp_cap_pool = create_pool("ptrcap",
7484 curproxy->nb_rsp_cap * sizeof(char *),
7485 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007486 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007487
Willy Tarreaubaaee002006-06-26 02:48:02 +02007488 /* first, we will invert the servers list order */
7489 newsrv = NULL;
7490 while (curproxy->srv) {
7491 struct server *next;
7492
7493 next = curproxy->srv->next;
7494 curproxy->srv->next = newsrv;
7495 newsrv = curproxy->srv;
7496 if (!next)
7497 break;
7498 curproxy->srv = next;
7499 }
7500
Willy Tarreau17edc812014-01-03 12:14:34 +01007501 /* Check that no server name conflicts. This causes trouble in the stats.
7502 * We only emit a warning for the first conflict affecting each server,
7503 * in order to avoid combinatory explosion if all servers have the same
7504 * name. We do that only for servers which do not have an explicit ID,
7505 * because these IDs were made also for distinguishing them and we don't
7506 * want to annoy people who correctly manage them.
7507 */
7508 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7509 struct server *other_srv;
7510
7511 if (newsrv->puid)
7512 continue;
7513
7514 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7515 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7516 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7517 newsrv->conf.file, newsrv->conf.line,
7518 proxy_type_str(curproxy), curproxy->id,
7519 newsrv->id, other_srv->conf.line);
7520 break;
7521 }
7522 }
7523 }
7524
Willy Tarreaudd701652010-05-25 23:03:02 +02007525 /* assign automatic UIDs to servers which don't have one yet */
7526 next_id = 1;
7527 newsrv = curproxy->srv;
7528 while (newsrv != NULL) {
7529 if (!newsrv->puid) {
7530 /* server ID not set, use automatic numbering with first
7531 * spare entry starting with next_svid.
7532 */
7533 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7534 newsrv->conf.id.key = newsrv->puid = next_id;
7535 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7536 }
7537 next_id++;
7538 newsrv = newsrv->next;
7539 }
7540
Willy Tarreau20697042007-11-15 23:26:18 +01007541 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007542 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007543
Willy Tarreau62c3be22012-01-20 13:12:32 +01007544 /*
7545 * If this server supports a maxconn parameter, it needs a dedicated
7546 * tasks to fill the emptied slots when a connection leaves.
7547 * Also, resolve deferred tracking dependency if needed.
7548 */
7549 newsrv = curproxy->srv;
7550 while (newsrv != NULL) {
7551 if (newsrv->minconn > newsrv->maxconn) {
7552 /* Only 'minconn' was specified, or it was higher than or equal
7553 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7554 * this will avoid further useless expensive computations.
7555 */
7556 newsrv->maxconn = newsrv->minconn;
7557 } else if (newsrv->maxconn && !newsrv->minconn) {
7558 /* minconn was not specified, so we set it to maxconn */
7559 newsrv->minconn = newsrv->maxconn;
7560 }
7561
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007562#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007563 if (newsrv->use_ssl || newsrv->check.use_ssl)
7564 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007565#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007566
Willy Tarreau2f075e92013-12-03 11:11:34 +01007567 /* set the check type on the server */
7568 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7569
Willy Tarreau62c3be22012-01-20 13:12:32 +01007570 if (newsrv->trackit) {
7571 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007572 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007573 char *pname, *sname;
7574
7575 pname = newsrv->trackit;
7576 sname = strrchr(pname, '/');
7577
7578 if (sname)
7579 *sname++ = '\0';
7580 else {
7581 sname = pname;
7582 pname = NULL;
7583 }
7584
7585 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007586 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007587 if (!px) {
7588 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7589 proxy_type_str(curproxy), curproxy->id,
7590 newsrv->id, pname);
7591 cfgerr++;
7592 goto next_srv;
7593 }
7594 } else
7595 px = curproxy;
7596
7597 srv = findserver(px, sname);
7598 if (!srv) {
7599 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7600 proxy_type_str(curproxy), curproxy->id,
7601 newsrv->id, sname);
7602 cfgerr++;
7603 goto next_srv;
7604 }
7605
Willy Tarreau32091232014-05-16 13:52:00 +02007606 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7607 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7608 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007609 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007610 "tracking as it does not have any check nor agent enabled.\n",
7611 proxy_type_str(curproxy), curproxy->id,
7612 newsrv->id, px->id, srv->id);
7613 cfgerr++;
7614 goto next_srv;
7615 }
7616
7617 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7618
7619 if (loop) {
7620 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7621 "belongs to a tracking chain looping back to %s/%s.\n",
7622 proxy_type_str(curproxy), curproxy->id,
7623 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007624 cfgerr++;
7625 goto next_srv;
7626 }
7627
7628 if (curproxy != px &&
7629 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7630 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7631 "tracking: disable-on-404 option inconsistency.\n",
7632 proxy_type_str(curproxy), curproxy->id,
7633 newsrv->id, px->id, srv->id);
7634 cfgerr++;
7635 goto next_srv;
7636 }
7637
7638 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007639 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007640 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007641 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007642 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007643 }
7644
7645 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007646 newsrv->tracknext = srv->trackers;
7647 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007648
7649 free(newsrv->trackit);
7650 newsrv->trackit = NULL;
7651 }
7652 next_srv:
7653 newsrv = newsrv->next;
7654 }
7655
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007656 /* We have to initialize the server lookup mechanism depending
7657 * on what LB algorithm was choosen.
7658 */
7659
7660 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7661 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7662 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007663 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7664 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7665 init_server_map(curproxy);
7666 } else {
7667 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7668 fwrr_init_server_groups(curproxy);
7669 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007670 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007671
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007672 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007673 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7674 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7675 fwlc_init_server_tree(curproxy);
7676 } else {
7677 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7678 fas_init_server_tree(curproxy);
7679 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007680 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007681
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007682 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007683 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7684 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7685 chash_init_server_tree(curproxy);
7686 } else {
7687 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7688 init_server_map(curproxy);
7689 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007690 break;
7691 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007692
7693 if (curproxy->options & PR_O_LOGASAP)
7694 curproxy->to_log &= ~LW_BYTES;
7695
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007696 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007697 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007698 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7699 proxy_type_str(curproxy), curproxy->id);
7700 err_code |= ERR_WARN;
7701 }
7702
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007703 if (curproxy->mode != PR_MODE_HTTP) {
7704 int optnum;
7705
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007706 if (curproxy->uri_auth) {
7707 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7708 proxy_type_str(curproxy), curproxy->id);
7709 err_code |= ERR_WARN;
7710 curproxy->uri_auth = NULL;
7711 }
7712
Willy Tarreau87cf5142011-08-19 22:57:24 +02007713 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007714 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7715 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7716 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007717 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007718 }
7719
7720 if (curproxy->options & PR_O_ORGTO) {
7721 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7722 "originalto", proxy_type_str(curproxy), curproxy->id);
7723 err_code |= ERR_WARN;
7724 curproxy->options &= ~PR_O_ORGTO;
7725 }
7726
7727 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7728 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7729 (curproxy->cap & cfg_opts[optnum].cap) &&
7730 (curproxy->options & cfg_opts[optnum].val)) {
7731 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7732 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7733 err_code |= ERR_WARN;
7734 curproxy->options &= ~cfg_opts[optnum].val;
7735 }
7736 }
7737
7738 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7739 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7740 (curproxy->cap & cfg_opts2[optnum].cap) &&
7741 (curproxy->options2 & cfg_opts2[optnum].val)) {
7742 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7743 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7744 err_code |= ERR_WARN;
7745 curproxy->options2 &= ~cfg_opts2[optnum].val;
7746 }
7747 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007748
Pieter Baauwd551fb52013-05-08 22:49:23 +02007749#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007750 if (curproxy->conn_src.bind_hdr_occ) {
7751 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007752 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007753 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007754 err_code |= ERR_WARN;
7755 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007756#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007757 }
7758
Willy Tarreaubaaee002006-06-26 02:48:02 +02007759 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007760 * ensure that we're not cross-dressing a TCP server into HTTP.
7761 */
7762 newsrv = curproxy->srv;
7763 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007764 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007765 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7766 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007767 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007768 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007769
Willy Tarreau0cec3312011-10-31 13:49:26 +01007770 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7771 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7772 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7773 err_code |= ERR_WARN;
7774 }
7775
Willy Tarreauc93cd162014-05-13 15:54:22 +02007776 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007777 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7778 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7779 err_code |= ERR_WARN;
7780 }
7781
Pieter Baauwd551fb52013-05-08 22:49:23 +02007782#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007783 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7784 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007785 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 +01007786 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007787 err_code |= ERR_WARN;
7788 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007789#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007790 newsrv = newsrv->next;
7791 }
7792
Willy Tarreaue42bd962014-09-16 16:21:19 +02007793 /* check if we have a frontend with "tcp-request content" looking at L7
7794 * with no inspect-delay
7795 */
7796 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7797 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7798 if (trule->action == TCP_ACT_CAPTURE &&
7799 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7800 break;
7801 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7802 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7803 break;
7804 }
7805
7806 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7807 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7808 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7809 " This means that these rules will randomly find their contents. This can be fixed by"
7810 " setting the tcp-request inspect-delay.\n",
7811 proxy_type_str(curproxy), curproxy->id);
7812 err_code |= ERR_WARN;
7813 }
7814 }
7815
Willy Tarreauc1a21672009-08-16 22:37:44 +02007816 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007817 if (!curproxy->accept)
7818 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007819
Willy Tarreauc1a21672009-08-16 22:37:44 +02007820 if (curproxy->tcp_req.inspect_delay ||
7821 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007822 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007823
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007824 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007825 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007826 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007827 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007828
7829 /* both TCP and HTTP must check switching rules */
7830 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7831 }
7832
7833 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007834 if (curproxy->tcp_req.inspect_delay ||
7835 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7836 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7837
Emeric Brun97679e72010-09-23 17:56:44 +02007838 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7839 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7840
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007841 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007842 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007843 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007844 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007845
7846 /* If the backend does requires RDP cookie persistence, we have to
7847 * enable the corresponding analyser.
7848 */
7849 if (curproxy->options2 & PR_O2_RDPC_PRST)
7850 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7851 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007852 }
7853
7854 /***********************************************************/
7855 /* At this point, target names have already been resolved. */
7856 /***********************************************************/
7857
7858 /* Check multi-process mode compatibility */
7859
7860 if (global.nbproc > 1 && global.stats_fe) {
7861 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7862 unsigned long mask;
7863
7864 mask = nbits(global.nbproc);
7865 if (global.stats_fe->bind_proc)
7866 mask &= global.stats_fe->bind_proc;
7867
7868 if (bind_conf->bind_proc)
7869 mask &= bind_conf->bind_proc;
7870
7871 /* stop here if more than one process is used */
7872 if (popcount(mask) > 1)
7873 break;
7874 }
7875 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7876 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");
7877 }
7878 }
7879
7880 /* Make each frontend inherit bind-process from its listeners when not specified. */
7881 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7882 if (curproxy->bind_proc)
7883 continue;
7884
7885 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7886 unsigned long mask;
7887
Willy Tarreaue428b082015-05-04 21:57:58 +02007888 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007889 curproxy->bind_proc |= mask;
7890 }
7891
7892 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02007893 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007894 }
7895
7896 if (global.stats_fe) {
7897 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7898 unsigned long mask;
7899
Willy Tarreaue428b082015-05-04 21:57:58 +02007900 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007901 global.stats_fe->bind_proc |= mask;
7902 }
7903 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02007904 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007905 }
7906
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007907 /* propagate bindings from frontends to backends. Don't do it if there
7908 * are any fatal errors as we must not call it with unresolved proxies.
7909 */
7910 if (!cfgerr) {
7911 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7912 if (curproxy->cap & PR_CAP_FE)
7913 propagate_processes(curproxy, NULL);
7914 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007915 }
7916
7917 /* Bind each unbound backend to all processes when not specified. */
7918 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7919 if (curproxy->bind_proc)
7920 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02007921 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007922 }
7923
7924 /*******************************************************/
7925 /* At this step, all proxies have a non-null bind_proc */
7926 /*******************************************************/
7927
7928 /* perform the final checks before creating tasks */
7929
7930 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7931 struct listener *listener;
7932 unsigned int next_id;
7933 int nbproc;
7934
7935 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007936
Emeric Brunc52962f2012-11-15 18:28:02 +01007937#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007938 /* Configure SSL for each bind line.
7939 * Note: if configuration fails at some point, the ->ctx member
7940 * remains NULL so that listeners can later detach.
7941 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007942 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007943 int alloc_ctx;
7944
Emeric Brunc52962f2012-11-15 18:28:02 +01007945 if (!bind_conf->is_ssl) {
7946 if (bind_conf->default_ctx) {
7947 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7948 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7949 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007950 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007951 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007952 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007953 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007954 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007955 cfgerr++;
7956 continue;
7957 }
7958
Emeric Brun8dc60392014-05-09 13:52:00 +02007959 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007960 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007961 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7962 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");
7963 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007964 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007965 cfgerr++;
7966 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007967 }
7968
Emeric Brunfc0421f2012-09-07 17:30:07 +02007969 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007970 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007971 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007972#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007973
Willy Tarreaue6b98942007-10-29 01:09:36 +01007974 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007975 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007976 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007977 if (!listener->luid) {
7978 /* listener ID not set, use automatic numbering with first
7979 * spare entry starting with next_luid.
7980 */
7981 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7982 listener->conf.id.key = listener->luid = next_id;
7983 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007984 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007985 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007986
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007987 /* enable separate counters */
7988 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7989 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007990 if (!listener->name)
7991 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007992 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007993
Willy Tarreaue6b98942007-10-29 01:09:36 +01007994 if (curproxy->options & PR_O_TCP_NOLING)
7995 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007996 if (!listener->maxconn)
7997 listener->maxconn = curproxy->maxconn;
7998 if (!listener->backlog)
7999 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008000 if (!listener->maxaccept)
8001 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8002
8003 /* we want to have an optimal behaviour on single process mode to
8004 * maximize the work at once, but in multi-process we want to keep
8005 * some fairness between processes, so we target half of the max
8006 * number of events to be balanced over all the processes the proxy
8007 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8008 * used to disable the limit.
8009 */
8010 if (listener->maxaccept > 0) {
8011 if (nbproc > 1)
8012 listener->maxaccept = (listener->maxaccept + 1) / 2;
8013 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8014 }
8015
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008016 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008017 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008018 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008019 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008020
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008021 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8022 listener->options |= LI_O_TCP_RULES;
8023
Willy Tarreaude3041d2010-05-31 10:56:17 +02008024 if (curproxy->mon_mask.s_addr)
8025 listener->options |= LI_O_CHK_MONNET;
8026
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008027 /* smart accept mode is automatic in HTTP mode */
8028 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008029 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008030 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8031 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008032 }
8033
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008034 /* Release unused SSL configs */
8035 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8036 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008037 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008038#ifdef USE_OPENSSL
8039 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008040 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008041 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008042 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008043 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008044 if(bind_conf->keys_ref) {
8045 free(bind_conf->keys_ref->filename);
8046 free(bind_conf->keys_ref->tlskeys);
8047 free(bind_conf->keys_ref);
8048 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008049#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008050 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008051
Willy Tarreau102df612014-05-07 23:56:38 +02008052 if (nbproc > 1) {
8053 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008054 int count, maxproc = 0;
8055
8056 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8057 count = popcount(bind_conf->bind_proc);
8058 if (count > maxproc)
8059 maxproc = count;
8060 }
8061 /* backends have 0, frontends have 1 or more */
8062 if (maxproc != 1)
8063 Warning("Proxy '%s': in multi-process mode, stats will be"
8064 " limited to process assigned to the current request.\n",
8065 curproxy->id);
8066
Willy Tarreau102df612014-05-07 23:56:38 +02008067 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8068 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8069 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008070 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008071 }
Willy Tarreau102df612014-05-07 23:56:38 +02008072 if (curproxy->appsession_name) {
8073 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
8074 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008075 }
Willy Tarreau102df612014-05-07 23:56:38 +02008076 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8077 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8078 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008079 }
8080 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008081
8082 /* create the task associated with the proxy */
8083 curproxy->task = task_new();
8084 if (curproxy->task) {
8085 curproxy->task->context = curproxy;
8086 curproxy->task->process = manage_proxy;
8087 /* no need to queue, it will be done automatically if some
8088 * listener gets limited.
8089 */
8090 curproxy->task->expire = TICK_ETERNITY;
8091 } else {
8092 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8093 curproxy->id);
8094 cfgerr++;
8095 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008096 }
8097
Willy Tarreaufbb78422011-06-05 15:38:35 +02008098 /* automatically compute fullconn if not set. We must not do it in the
8099 * loop above because cross-references are not yet fully resolved.
8100 */
8101 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8102 /* If <fullconn> is not set, let's set it to 10% of the sum of
8103 * the possible incoming frontend's maxconns.
8104 */
8105 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8106 struct proxy *fe;
8107 int total = 0;
8108
8109 /* sum up the number of maxconns of frontends which
8110 * reference this backend at least once or which are
8111 * the same one ('listen').
8112 */
8113 for (fe = proxy; fe; fe = fe->next) {
8114 struct switching_rule *rule;
8115 struct hdr_exp *exp;
8116 int found = 0;
8117
8118 if (!(fe->cap & PR_CAP_FE))
8119 continue;
8120
8121 if (fe == curproxy) /* we're on a "listen" instance */
8122 found = 1;
8123
8124 if (fe->defbe.be == curproxy) /* "default_backend" */
8125 found = 1;
8126
8127 /* check if a "use_backend" rule matches */
8128 if (!found) {
8129 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008130 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008131 found = 1;
8132 break;
8133 }
8134 }
8135 }
8136
8137 /* check if a "reqsetbe" rule matches */
8138 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
8139 if (exp->action == ACT_SETBE &&
8140 (struct proxy *)exp->replace == curproxy) {
8141 found = 1;
8142 break;
8143 }
8144 }
8145
8146 /* now we've checked all possible ways to reference a backend
8147 * from a frontend.
8148 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008149 if (!found)
8150 continue;
8151 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008152 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008153 /* we have the sum of the maxconns in <total>. We only
8154 * keep 10% of that sum to set the default fullconn, with
8155 * a hard minimum of 1 (to avoid a divide by zero).
8156 */
8157 curproxy->fullconn = (total + 9) / 10;
8158 if (!curproxy->fullconn)
8159 curproxy->fullconn = 1;
8160 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008161 }
8162
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008163 /*
8164 * Recount currently required checks.
8165 */
8166
8167 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8168 int optnum;
8169
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008170 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8171 if (curproxy->options & cfg_opts[optnum].val)
8172 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008173
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008174 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8175 if (curproxy->options2 & cfg_opts2[optnum].val)
8176 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008177 }
8178
Willy Tarreau0fca4832015-05-01 19:12:05 +02008179 /* compute the required process bindings for the peers */
8180 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8181 if (curproxy->table.peers.p)
8182 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8183
Willy Tarreau122541c2011-09-07 21:24:49 +02008184 if (peers) {
8185 struct peers *curpeers = peers, **last;
8186 struct peer *p, *pb;
8187
Willy Tarreau1e273012015-05-01 19:15:17 +02008188 /* Remove all peers sections which don't have a valid listener,
8189 * which are not used by any table, or which are bound to more
8190 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008191 */
8192 last = &peers;
8193 while (*last) {
8194 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008195
8196 if (curpeers->state == PR_STSTOPPED) {
8197 /* the "disabled" keyword was present */
8198 if (curpeers->peers_fe)
8199 stop_proxy(curpeers->peers_fe);
8200 curpeers->peers_fe = NULL;
8201 }
8202 else if (!curpeers->peers_fe) {
8203 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8204 curpeers->id, localpeer);
8205 }
Willy Tarreau1e273012015-05-01 19:15:17 +02008206 else if (popcount(curpeers->peers_fe->bind_proc) != 1) {
8207 /* either it's totally stopped or too much used */
8208 if (curpeers->peers_fe->bind_proc) {
8209 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008210 "running in different processes (%d different ones). "
8211 "Check global.nbproc and all tables' bind-process "
8212 "settings.\n", curpeers->id, popcount(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008213 cfgerr++;
8214 }
8215 stop_proxy(curpeers->peers_fe);
8216 curpeers->peers_fe = NULL;
8217 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008218 else {
Willy Tarreau122541c2011-09-07 21:24:49 +02008219 last = &curpeers->next;
8220 continue;
8221 }
8222
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008223 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008224 p = curpeers->remote;
8225 while (p) {
8226 pb = p->next;
8227 free(p->id);
8228 free(p);
8229 p = pb;
8230 }
8231
8232 /* Destroy and unlink this curpeers section.
8233 * Note: curpeers is backed up into *last.
8234 */
8235 free(curpeers->id);
8236 curpeers = curpeers->next;
8237 free(*last);
8238 *last = curpeers;
8239 }
8240 }
8241
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008242 /* initialize stick-tables on backend capable proxies. This must not
8243 * be done earlier because the data size may be discovered while parsing
8244 * other proxies.
8245 */
8246 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8247 if (curproxy->state == PR_STSTOPPED)
8248 continue;
8249
8250 if (!stktable_init(&curproxy->table)) {
8251 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8252 cfgerr++;
8253 }
8254 }
8255
Simon Horman0d16a402015-01-30 11:22:58 +09008256 if (mailers) {
8257 struct mailers *curmailers = mailers, **last;
8258 struct mailer *m, *mb;
8259
8260 /* Remove all mailers sections which don't have a valid listener.
8261 * This can happen when a mailers section is never referenced.
8262 */
8263 last = &mailers;
8264 while (*last) {
8265 curmailers = *last;
8266 if (curmailers->users) {
8267 last = &curmailers->next;
8268 continue;
8269 }
8270
8271 Warning("Removing incomplete section 'mailers %s'.\n",
8272 curmailers->id);
8273
8274 m = curmailers->mailer_list;
8275 while (m) {
8276 mb = m->next;
8277 free(m->id);
8278 free(m);
8279 m = mb;
8280 }
8281
8282 /* Destroy and unlink this curmailers section.
8283 * Note: curmailers is backed up into *last.
8284 */
8285 free(curmailers->id);
8286 curmailers = curmailers->next;
8287 free(*last);
8288 *last = curmailers;
8289 }
8290 }
8291
Willy Tarreau34eb6712011-10-24 18:15:04 +02008292 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008293 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008294 MEM_F_SHARED);
8295
Willy Tarreaubb925012009-07-23 13:36:36 +02008296 if (cfgerr > 0)
8297 err_code |= ERR_ALERT | ERR_FATAL;
8298 out:
8299 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008300}
8301
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008302/*
8303 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8304 * parsing sessions.
8305 */
8306void cfg_register_keywords(struct cfg_kw_list *kwl)
8307{
8308 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8309}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008310
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008311/*
8312 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8313 */
8314void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8315{
8316 LIST_DEL(&kwl->list);
8317 LIST_INIT(&kwl->list);
8318}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008319
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008320/* this function register new section in the haproxy configuration file.
8321 * <section_name> is the name of this new section and <section_parser>
8322 * is the called parser. If two section declaration have the same name,
8323 * only the first declared is used.
8324 */
8325int cfg_register_section(char *section_name,
8326 int (*section_parser)(const char *, int, char **, int))
8327{
8328 struct cfg_section *cs;
8329
8330 cs = calloc(1, sizeof(*cs));
8331 if (!cs) {
8332 Alert("register section '%s': out of memory.\n", section_name);
8333 return 0;
8334 }
8335
8336 cs->section_name = section_name;
8337 cs->section_parser = section_parser;
8338
8339 LIST_ADDQ(&sections, &cs->list);
8340
8341 return 1;
8342}
8343
Willy Tarreaubaaee002006-06-26 02:48:02 +02008344/*
8345 * Local variables:
8346 * c-indent-level: 8
8347 * c-basic-offset: 8
8348 * End:
8349 */