blob: b96a27199bf41fdad85fb4a3e0bc755dd3d500ee [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 },
163 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
164 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100165#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100166 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100167#else
168 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100169#endif
170
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100172};
173
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100174/* proxy->options2 */
175static const struct cfg_opt cfg_opts2[] =
176{
177#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100178 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
179 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
180 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100181#else
182 { "splice-request", 0, 0, 0, 0 },
183 { "splice-response", 0, 0, 0, 0 },
184 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100185#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100186 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
187 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
188 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
189 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
190 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
191 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
192 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
193 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
194 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400195 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100196 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200197 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200198 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100199 { NULL, 0, 0, 0 }
200};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201
Willy Tarreau6daf3432008-01-22 16:44:08 +0100202static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
204int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100205int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200207/* List head of all known configuration keywords */
208static struct cfg_kw_list cfg_keywords = {
209 .list = LIST_HEAD_INIT(cfg_keywords.list)
210};
211
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212/*
213 * converts <str> to a list of listeners which are dynamically allocated.
214 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
215 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
216 * - <port> is a numerical port from 1 to 65535 ;
217 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
218 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
220 * not NULL, it must be a valid pointer to either NULL or a freeable area that
221 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200223int 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 +0200224{
225 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 int port, end;
228
229 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200230
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100232 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100233 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234
235 str = next;
236 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100237 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 *next++ = 0;
239 }
240
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100241 ss2 = str2sa_range(str, &port, &end, err,
242 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
243 if (!ss2)
244 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200245
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100246 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100247 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200248 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100249 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100252 if (!port || !end) {
253 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
254 goto fail;
255 }
256
Emeric Bruned760922010-10-22 17:59:25 +0200257 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200258 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200259 goto fail;
260 }
261
262 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200263 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200264 goto fail;
265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100267 else if (ss2->ss_family == AF_UNSPEC) {
268 socklen_t addr_len;
269
270 /* We want to attach to an already bound fd whose number
271 * is in the addr part of ss2 when cast to sockaddr_in.
272 * Note that by definition there is a single listener.
273 * We still have to determine the address family to
274 * register the correct protocol.
275 */
276 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
277 addr_len = sizeof(*ss2);
278 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
279 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
280 goto fail;
281 }
282
283 port = end = get_host_port(ss2);
284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100286 /* OK the address looks correct */
287 ss = *ss2;
288
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289 for (; port <= end; port++) {
290 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100291 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200292 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
293 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
294 l->frontend = curproxy;
295 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296
Willy Tarreau40aa0702013-03-10 23:51:38 +0100297 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200299 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100300 l->state = LI_INIT;
301
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100302 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200303 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100304 tcpv4_add_listener(l);
305 }
Emeric Bruned760922010-10-22 17:59:25 +0200306 else if (ss.ss_family == AF_INET6) {
307 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
308 tcpv6_add_listener(l);
309 }
310 else {
Emeric Bruned760922010-10-22 17:59:25 +0200311 uxst_add_listener(l);
312 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200313
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200314 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100315 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200316 } /* end for(port) */
317 } /* end while(next) */
318 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200319 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200320 fail:
321 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200322 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200323}
324
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200325/* Report a warning if a rule is placed after a 'tcp-request content' rule.
326 * Return 1 if the warning has been emitted, otherwise 0.
327 */
328int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
329{
330 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
331 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
332 file, line, arg);
333 return 1;
334 }
335 return 0;
336}
337
Willy Tarreau61d18892009-03-31 10:49:21 +0200338/* Report a warning if a rule is placed after a 'block' rule.
339 * Return 1 if the warning has been emitted, otherwise 0.
340 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100341int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200342{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200343 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200344 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
345 file, line, arg);
346 return 1;
347 }
348 return 0;
349}
350
Willy Tarreau5002f572014-04-23 01:32:02 +0200351/* Report a warning if a rule is placed after an 'http_request' rule.
352 * Return 1 if the warning has been emitted, otherwise 0.
353 */
354int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
355{
356 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
357 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
358 file, line, arg);
359 return 1;
360 }
361 return 0;
362}
363
Willy Tarreau61d18892009-03-31 10:49:21 +0200364/* Report a warning if a rule is placed after a reqrewrite rule.
365 * Return 1 if the warning has been emitted, otherwise 0.
366 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100367int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200368{
369 if (proxy->req_exp) {
370 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
371 file, line, arg);
372 return 1;
373 }
374 return 0;
375}
376
377/* Report a warning if a rule is placed after a reqadd rule.
378 * Return 1 if the warning has been emitted, otherwise 0.
379 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100380int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200381{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100382 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200383 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
384 file, line, arg);
385 return 1;
386 }
387 return 0;
388}
389
390/* Report a warning if a rule is placed after a redirect rule.
391 * Return 1 if the warning has been emitted, otherwise 0.
392 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100393int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200394{
395 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
396 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
397 file, line, arg);
398 return 1;
399 }
400 return 0;
401}
402
403/* Report a warning if a rule is placed after a 'use_backend' rule.
404 * Return 1 if the warning has been emitted, otherwise 0.
405 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100406int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200407{
408 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
409 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
410 file, line, arg);
411 return 1;
412 }
413 return 0;
414}
415
Willy Tarreauee445d92014-04-23 01:39:04 +0200416/* Report a warning if a rule is placed after a 'use-server' rule.
417 * Return 1 if the warning has been emitted, otherwise 0.
418 */
419int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
420{
421 if (!LIST_ISEMPTY(&proxy->server_rules)) {
422 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
423 file, line, arg);
424 return 1;
425 }
426 return 0;
427}
428
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200429/* report a warning if a "tcp request connection" rule is dangerously placed */
430int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
431{
432 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
433 warnif_rule_after_block(proxy, file, line, arg) ||
434 warnif_rule_after_http_req(proxy, file, line, arg) ||
435 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
436 warnif_rule_after_reqadd(proxy, file, line, arg) ||
437 warnif_rule_after_redirect(proxy, file, line, arg) ||
438 warnif_rule_after_use_backend(proxy, file, line, arg) ||
439 warnif_rule_after_use_server(proxy, file, line, arg);
440}
441
442/* report a warning if a "tcp request content" rule is dangerously placed */
443int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
444{
445 return warnif_rule_after_block(proxy, file, line, arg) ||
446 warnif_rule_after_http_req(proxy, file, line, arg) ||
447 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
448 warnif_rule_after_reqadd(proxy, file, line, arg) ||
449 warnif_rule_after_redirect(proxy, file, line, arg) ||
450 warnif_rule_after_use_backend(proxy, file, line, arg) ||
451 warnif_rule_after_use_server(proxy, file, line, arg);
452}
453
Willy Tarreau61d18892009-03-31 10:49:21 +0200454/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100455int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200456{
Willy Tarreau5002f572014-04-23 01:32:02 +0200457 return warnif_rule_after_http_req(proxy, file, line, arg) ||
458 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
459 warnif_rule_after_reqadd(proxy, file, line, arg) ||
460 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200461 warnif_rule_after_use_backend(proxy, file, line, arg) ||
462 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200463}
464
465/* report a warning if an http-request rule is dangerously placed */
466int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
467{
Willy Tarreau61d18892009-03-31 10:49:21 +0200468 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
469 warnif_rule_after_reqadd(proxy, file, line, arg) ||
470 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200471 warnif_rule_after_use_backend(proxy, file, line, arg) ||
472 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200473}
474
475/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100476int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200477{
478 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
479 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200480 warnif_rule_after_use_backend(proxy, file, line, arg) ||
481 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200482}
483
484/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100485int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200486{
487 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200488 warnif_rule_after_use_backend(proxy, file, line, arg) ||
489 warnif_rule_after_use_server(proxy, file, line, arg);
490}
491
492/* report a warning if a redirect rule is dangerously placed */
493int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
494{
495 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
496 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200497}
498
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100499/* Report it if a request ACL condition uses some keywords that are incompatible
500 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
501 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
502 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100503 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100504static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100505{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100506 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200507 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100508
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100509 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100510 return 0;
511
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100512 acl = acl_cond_conflicts(cond, where);
513 if (acl) {
514 if (acl->name && *acl->name)
515 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
516 file, line, acl->name, sample_ckp_names(where));
517 else
518 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 +0200519 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100520 return ERR_WARN;
521 }
522 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100523 return 0;
524
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100525 if (acl->name && *acl->name)
526 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200527 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100528 else
529 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200530 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100531 return ERR_WARN;
532}
533
Willy Tarreaubaaee002006-06-26 02:48:02 +0200534/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200535 * parse a line in a <global> section. Returns the error code, 0 if OK, or
536 * any combination of :
537 * - ERR_ABORT: must abort ASAP
538 * - ERR_FATAL: we can continue parsing but not start the service
539 * - ERR_WARN: a warning has been emitted
540 * - ERR_ALERT: an alert has been emitted
541 * Only the two first ones can stop processing, the two others are just
542 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200543 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200544int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200545{
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200547 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548
549 if (!strcmp(args[0], "global")) { /* new section */
550 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200552 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200553 else if (!strcmp(args[0], "ca-base")) {
554#ifdef USE_OPENSSL
555 if (global.ca_base != NULL) {
556 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
557 err_code |= ERR_ALERT;
558 goto out;
559 }
560 if (*(args[1]) == 0) {
561 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
562 err_code |= ERR_ALERT | ERR_FATAL;
563 goto out;
564 }
565 global.ca_base = strdup(args[1]);
566#else
567 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
568 err_code |= ERR_ALERT | ERR_FATAL;
569 goto out;
570#endif
571 }
572 else if (!strcmp(args[0], "crt-base")) {
573#ifdef USE_OPENSSL
574 if (global.crt_base != NULL) {
575 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
576 err_code |= ERR_ALERT;
577 goto out;
578 }
579 if (*(args[1]) == 0) {
580 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
581 err_code |= ERR_ALERT | ERR_FATAL;
582 goto out;
583 }
584 global.crt_base = strdup(args[1]);
585#else
586 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589#endif
590 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200591 else if (!strcmp(args[0], "daemon")) {
592 global.mode |= MODE_DAEMON;
593 }
594 else if (!strcmp(args[0], "debug")) {
595 global.mode |= MODE_DEBUG;
596 }
597 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100598 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200600 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100601 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200603 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100604 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200605 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100606 else if (!strcmp(args[0], "nosplice")) {
607 global.tune.options &= ~GTUNE_USE_SPLICE;
608 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200609 else if (!strcmp(args[0], "nogetaddrinfo")) {
610 global.tune.options &= ~GTUNE_USE_GAI;
611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 else if (!strcmp(args[0], "quiet")) {
613 global.mode |= MODE_QUIET;
614 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200615 else if (!strcmp(args[0], "tune.maxpollevents")) {
616 if (global.tune.maxpollevents != 0) {
617 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200618 err_code |= ERR_ALERT;
619 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200620 }
621 if (*(args[1]) == 0) {
622 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200623 err_code |= ERR_ALERT | ERR_FATAL;
624 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200625 }
626 global.tune.maxpollevents = atol(args[1]);
627 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100628 else if (!strcmp(args[0], "tune.maxaccept")) {
629 if (global.tune.maxaccept != 0) {
630 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200631 err_code |= ERR_ALERT;
632 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100633 }
634 if (*(args[1]) == 0) {
635 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200636 err_code |= ERR_ALERT | ERR_FATAL;
637 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100638 }
639 global.tune.maxaccept = atol(args[1]);
640 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200641 else if (!strcmp(args[0], "tune.chksize")) {
642 if (*(args[1]) == 0) {
643 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
644 err_code |= ERR_ALERT | ERR_FATAL;
645 goto out;
646 }
647 global.tune.chksize = atol(args[1]);
648 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200649#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200650 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
651 global.tune.sslprivatecache = 1;
652 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100653 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200654 if (*(args[1]) == 0) {
655 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
656 err_code |= ERR_ALERT | ERR_FATAL;
657 goto out;
658 }
659 global.tune.sslcachesize = atol(args[1]);
660 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100661 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
662 unsigned int ssllifetime;
663 const char *res;
664
665 if (*(args[1]) == 0) {
666 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
667 err_code |= ERR_ALERT | ERR_FATAL;
668 goto out;
669 }
670
671 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
672 if (res) {
673 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
674 file, linenum, *res, args[0]);
675 err_code |= ERR_ALERT | ERR_FATAL;
676 goto out;
677 }
678
679 global.tune.ssllifetime = ssllifetime;
680 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100681 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
682 if (*(args[1]) == 0) {
683 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
684 err_code |= ERR_ALERT | ERR_FATAL;
685 goto out;
686 }
687 global.tune.ssl_max_record = atol(args[1]);
688 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200689 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
690 if (*(args[1]) == 0) {
691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
694 }
695 global.tune.ssl_default_dh_param = atol(args[1]);
696 if (global.tune.ssl_default_dh_param < 1024) {
697 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
698 err_code |= ERR_ALERT | ERR_FATAL;
699 goto out;
700 }
701 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200702#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100703 else if (!strcmp(args[0], "tune.buffers.limit")) {
704 if (*(args[1]) == 0) {
705 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
706 err_code |= ERR_ALERT | ERR_FATAL;
707 goto out;
708 }
709 global.tune.buf_limit = atol(args[1]);
710 if (global.tune.buf_limit) {
711 if (global.tune.buf_limit < 3)
712 global.tune.buf_limit = 3;
713 if (global.tune.buf_limit <= global.tune.reserved_bufs)
714 global.tune.buf_limit = global.tune.reserved_bufs + 1;
715 }
716 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100717 else if (!strcmp(args[0], "tune.buffers.reserve")) {
718 if (*(args[1]) == 0) {
719 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
720 err_code |= ERR_ALERT | ERR_FATAL;
721 goto out;
722 }
723 global.tune.reserved_bufs = atol(args[1]);
724 if (global.tune.reserved_bufs < 2)
725 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100726 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
727 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100728 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200729 else if (!strcmp(args[0], "tune.bufsize")) {
730 if (*(args[1]) == 0) {
731 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
734 }
735 global.tune.bufsize = atol(args[1]);
736 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
737 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100738 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100739 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200740 }
741 else if (!strcmp(args[0], "tune.maxrewrite")) {
742 if (*(args[1]) == 0) {
743 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
744 err_code |= ERR_ALERT | ERR_FATAL;
745 goto out;
746 }
747 global.tune.maxrewrite = atol(args[1]);
748 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
749 global.tune.maxrewrite = global.tune.bufsize / 2;
750 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100751 else if (!strcmp(args[0], "tune.idletimer")) {
752 unsigned int idle;
753 const char *res;
754
755 if (*(args[1]) == 0) {
756 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
757 err_code |= ERR_ALERT | ERR_FATAL;
758 goto out;
759 }
760
761 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
762 if (res) {
763 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
764 file, linenum, *res, args[0]);
765 err_code |= ERR_ALERT | ERR_FATAL;
766 goto out;
767 }
768
769 if (idle > 65535) {
770 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
771 err_code |= ERR_ALERT | ERR_FATAL;
772 goto out;
773 }
774 global.tune.idle_timer = idle;
775 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100776 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
777 if (global.tune.client_rcvbuf != 0) {
778 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
779 err_code |= ERR_ALERT;
780 goto out;
781 }
782 if (*(args[1]) == 0) {
783 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
784 err_code |= ERR_ALERT | ERR_FATAL;
785 goto out;
786 }
787 global.tune.client_rcvbuf = atol(args[1]);
788 }
789 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
790 if (global.tune.server_rcvbuf != 0) {
791 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
792 err_code |= ERR_ALERT;
793 goto out;
794 }
795 if (*(args[1]) == 0) {
796 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799 }
800 global.tune.server_rcvbuf = atol(args[1]);
801 }
802 else if (!strcmp(args[0], "tune.sndbuf.client")) {
803 if (global.tune.client_sndbuf != 0) {
804 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
805 err_code |= ERR_ALERT;
806 goto out;
807 }
808 if (*(args[1]) == 0) {
809 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
810 err_code |= ERR_ALERT | ERR_FATAL;
811 goto out;
812 }
813 global.tune.client_sndbuf = atol(args[1]);
814 }
815 else if (!strcmp(args[0], "tune.sndbuf.server")) {
816 if (global.tune.server_sndbuf != 0) {
817 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
818 err_code |= ERR_ALERT;
819 goto out;
820 }
821 if (*(args[1]) == 0) {
822 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
823 err_code |= ERR_ALERT | ERR_FATAL;
824 goto out;
825 }
826 global.tune.server_sndbuf = atol(args[1]);
827 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200828 else if (!strcmp(args[0], "tune.pipesize")) {
829 if (*(args[1]) == 0) {
830 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
831 err_code |= ERR_ALERT | ERR_FATAL;
832 goto out;
833 }
834 global.tune.pipesize = atol(args[1]);
835 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100836 else if (!strcmp(args[0], "tune.http.cookielen")) {
837 if (*(args[1]) == 0) {
838 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
839 err_code |= ERR_ALERT | ERR_FATAL;
840 goto out;
841 }
842 global.tune.cookie_len = atol(args[1]) + 1;
843 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200844 else if (!strcmp(args[0], "tune.http.maxhdr")) {
845 if (*(args[1]) == 0) {
846 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
847 err_code |= ERR_ALERT | ERR_FATAL;
848 goto out;
849 }
850 global.tune.max_http_hdr = atol(args[1]);
851 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100852 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
853#ifdef USE_ZLIB
854 if (*args[1]) {
855 global.tune.zlibmemlevel = atoi(args[1]);
856 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
857 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
858 file, linenum, args[0]);
859 err_code |= ERR_ALERT | ERR_FATAL;
860 goto out;
861 }
862 } else {
863 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
864 file, linenum, args[0]);
865 err_code |= ERR_ALERT | ERR_FATAL;
866 goto out;
867 }
868#else
869 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
872#endif
873 }
874 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
875#ifdef USE_ZLIB
876 if (*args[1]) {
877 global.tune.zlibwindowsize = atoi(args[1]);
878 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
879 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
880 file, linenum, args[0]);
881 err_code |= ERR_ALERT | ERR_FATAL;
882 goto out;
883 }
884 } else {
885 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
886 file, linenum, args[0]);
887 err_code |= ERR_ALERT | ERR_FATAL;
888 goto out;
889 }
890#else
891 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
892 err_code |= ERR_ALERT | ERR_FATAL;
893 goto out;
894#endif
895 }
William Lallemandf3747832012-11-09 12:33:10 +0100896 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
897 if (*args[1]) {
898 global.tune.comp_maxlevel = atoi(args[1]);
899 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
900 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
901 file, linenum, args[0]);
902 err_code |= ERR_ALERT | ERR_FATAL;
903 goto out;
904 }
905 } else {
906 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
907 file, linenum, args[0]);
908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
910 }
911 }
Willy Tarreauf3045d22015-04-29 16:24:50 +0200912 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
913 if (*args[1]) {
914 global.tune.pattern_cache = atoi(args[1]);
915 if (global.tune.pattern_cache < 0) {
916 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
917 file, linenum, args[0]);
918 err_code |= ERR_ALERT | ERR_FATAL;
919 goto out;
920 }
921 } else {
922 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
923 file, linenum, args[0]);
924 err_code |= ERR_ALERT | ERR_FATAL;
925 goto out;
926 }
927 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200928 else if (!strcmp(args[0], "uid")) {
929 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200930 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200931 err_code |= ERR_ALERT;
932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 }
934 if (*(args[1]) == 0) {
935 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200936 err_code |= ERR_ALERT | ERR_FATAL;
937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200938 }
939 global.uid = atol(args[1]);
940 }
941 else if (!strcmp(args[0], "gid")) {
942 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200943 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200944 err_code |= ERR_ALERT;
945 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200946 }
947 if (*(args[1]) == 0) {
948 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200949 err_code |= ERR_ALERT | ERR_FATAL;
950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 }
952 global.gid = atol(args[1]);
953 }
Simon Horman98637e52014-06-20 12:30:16 +0900954 else if (!strcmp(args[0], "external-check")) {
955 global.external_check = 1;
956 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200957 /* user/group name handling */
958 else if (!strcmp(args[0], "user")) {
959 struct passwd *ha_user;
960 if (global.uid != 0) {
961 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200962 err_code |= ERR_ALERT;
963 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200964 }
965 errno = 0;
966 ha_user = getpwnam(args[1]);
967 if (ha_user != NULL) {
968 global.uid = (int)ha_user->pw_uid;
969 }
970 else {
971 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 +0200972 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200973 }
974 }
975 else if (!strcmp(args[0], "group")) {
976 struct group *ha_group;
977 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200978 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200979 err_code |= ERR_ALERT;
980 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200981 }
982 errno = 0;
983 ha_group = getgrnam(args[1]);
984 if (ha_group != NULL) {
985 global.gid = (int)ha_group->gr_gid;
986 }
987 else {
988 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 +0200989 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200990 }
991 }
992 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200993 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200994 if (*(args[1]) == 0) {
995 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200996 err_code |= ERR_ALERT | ERR_FATAL;
997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200998 }
999 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001000 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1001 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1002 file, linenum, args[0], LONGBITS, global.nbproc);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001006 }
1007 else if (!strcmp(args[0], "maxconn")) {
1008 if (global.maxconn != 0) {
1009 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001010 err_code |= ERR_ALERT;
1011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001012 }
1013 if (*(args[1]) == 0) {
1014 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001015 err_code |= ERR_ALERT | ERR_FATAL;
1016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017 }
1018 global.maxconn = atol(args[1]);
1019#ifdef SYSTEM_MAXCONN
1020 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1021 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);
1022 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001023 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001024 }
1025#endif /* SYSTEM_MAXCONN */
1026 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001027 else if (!strcmp(args[0], "maxsslconn")) {
1028#ifdef USE_OPENSSL
1029 if (*(args[1]) == 0) {
1030 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1031 err_code |= ERR_ALERT | ERR_FATAL;
1032 goto out;
1033 }
1034 global.maxsslconn = atol(args[1]);
1035#else
Emeric Brun0914df82012-10-02 18:45:42 +02001036 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1037 err_code |= ERR_ALERT | ERR_FATAL;
1038 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001039#endif
1040 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001041 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1042#ifdef USE_OPENSSL
1043 if (*(args[1]) == 0) {
1044 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1045 err_code |= ERR_ALERT | ERR_FATAL;
1046 goto out;
1047 }
1048 free(global.listen_default_ciphers);
1049 global.listen_default_ciphers = strdup(args[1]);
1050#else
1051 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1052 err_code |= ERR_ALERT | ERR_FATAL;
1053 goto out;
1054#endif
1055 }
1056 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1057#ifdef USE_OPENSSL
1058 if (*(args[1]) == 0) {
1059 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1060 err_code |= ERR_ALERT | ERR_FATAL;
1061 goto out;
1062 }
1063 free(global.connect_default_ciphers);
1064 global.connect_default_ciphers = strdup(args[1]);
1065#else
1066 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1067 err_code |= ERR_ALERT | ERR_FATAL;
1068 goto out;
1069#endif
1070 }
Emeric Brun850efd52014-01-29 12:24:34 +01001071 else if (!strcmp(args[0], "ssl-server-verify")) {
1072 if (*(args[1]) == 0) {
1073 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1074 err_code |= ERR_ALERT | ERR_FATAL;
1075 goto out;
1076 }
1077 if (strcmp(args[1],"none") == 0)
1078 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1079 else if (strcmp(args[1],"required") == 0)
1080 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1081 else {
1082 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1083 err_code |= ERR_ALERT | ERR_FATAL;
1084 goto out;
1085 }
1086 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001087 else if (!strcmp(args[0], "maxconnrate")) {
1088 if (global.cps_lim != 0) {
1089 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1090 err_code |= ERR_ALERT;
1091 goto out;
1092 }
1093 if (*(args[1]) == 0) {
1094 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto out;
1097 }
1098 global.cps_lim = atol(args[1]);
1099 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001100 else if (!strcmp(args[0], "maxsessrate")) {
1101 if (global.sps_lim != 0) {
1102 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1103 err_code |= ERR_ALERT;
1104 goto out;
1105 }
1106 if (*(args[1]) == 0) {
1107 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1108 err_code |= ERR_ALERT | ERR_FATAL;
1109 goto out;
1110 }
1111 global.sps_lim = atol(args[1]);
1112 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001113 else if (!strcmp(args[0], "maxsslrate")) {
1114 if (global.ssl_lim != 0) {
1115 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1116 err_code |= ERR_ALERT;
1117 goto out;
1118 }
1119 if (*(args[1]) == 0) {
1120 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1121 err_code |= ERR_ALERT | ERR_FATAL;
1122 goto out;
1123 }
1124 global.ssl_lim = atol(args[1]);
1125 }
William Lallemandd85f9172012-11-09 17:05:39 +01001126 else if (!strcmp(args[0], "maxcomprate")) {
1127 if (*(args[1]) == 0) {
1128 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1129 err_code |= ERR_ALERT | ERR_FATAL;
1130 goto out;
1131 }
1132 global.comp_rate_lim = atoi(args[1]) * 1024;
1133 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001134 else if (!strcmp(args[0], "maxpipes")) {
1135 if (global.maxpipes != 0) {
1136 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001137 err_code |= ERR_ALERT;
1138 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001139 }
1140 if (*(args[1]) == 0) {
1141 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001142 err_code |= ERR_ALERT | ERR_FATAL;
1143 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001144 }
1145 global.maxpipes = atol(args[1]);
1146 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001147 else if (!strcmp(args[0], "maxzlibmem")) {
1148 if (*(args[1]) == 0) {
1149 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1150 err_code |= ERR_ALERT | ERR_FATAL;
1151 goto out;
1152 }
William Lallemande3a7d992012-11-20 11:25:20 +01001153 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001154 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001155 else if (!strcmp(args[0], "maxcompcpuusage")) {
1156 if (*(args[1]) == 0) {
1157 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1158 err_code |= ERR_ALERT | ERR_FATAL;
1159 goto out;
1160 }
1161 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001162 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001163 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1164 err_code |= ERR_ALERT | ERR_FATAL;
1165 goto out;
1166 }
1167}
1168
Willy Tarreaubaaee002006-06-26 02:48:02 +02001169 else if (!strcmp(args[0], "ulimit-n")) {
1170 if (global.rlimit_nofile != 0) {
1171 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001172 err_code |= ERR_ALERT;
1173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001174 }
1175 if (*(args[1]) == 0) {
1176 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001177 err_code |= ERR_ALERT | ERR_FATAL;
1178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001179 }
1180 global.rlimit_nofile = atol(args[1]);
1181 }
1182 else if (!strcmp(args[0], "chroot")) {
1183 if (global.chroot != NULL) {
1184 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001185 err_code |= ERR_ALERT;
1186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001187 }
1188 if (*(args[1]) == 0) {
1189 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001190 err_code |= ERR_ALERT | ERR_FATAL;
1191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001192 }
1193 global.chroot = strdup(args[1]);
1194 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001195 else if (!strcmp(args[0], "description")) {
1196 int i, len=0;
1197 char *d;
1198
1199 if (!*args[1]) {
1200 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1201 file, linenum, args[0]);
1202 err_code |= ERR_ALERT | ERR_FATAL;
1203 goto out;
1204 }
1205
Willy Tarreau348acfe2014-04-14 15:00:39 +02001206 for (i = 1; *args[i]; i++)
1207 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001208
1209 if (global.desc)
1210 free(global.desc);
1211
1212 global.desc = d = (char *)calloc(1, len);
1213
Willy Tarreau348acfe2014-04-14 15:00:39 +02001214 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1215 for (i = 2; *args[i]; i++)
1216 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001217 }
1218 else if (!strcmp(args[0], "node")) {
1219 int i;
1220 char c;
1221
1222 for (i=0; args[1][i]; i++) {
1223 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001224 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1225 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001226 break;
1227 }
1228
1229 if (!i || args[1][i]) {
1230 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1231 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1232 file, linenum, args[0]);
1233 err_code |= ERR_ALERT | ERR_FATAL;
1234 goto out;
1235 }
1236
1237 if (global.node)
1238 free(global.node);
1239
1240 global.node = strdup(args[1]);
1241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001242 else if (!strcmp(args[0], "pidfile")) {
1243 if (global.pidfile != NULL) {
1244 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001245 err_code |= ERR_ALERT;
1246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001247 }
1248 if (*(args[1]) == 0) {
1249 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001250 err_code |= ERR_ALERT | ERR_FATAL;
1251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001252 }
1253 global.pidfile = strdup(args[1]);
1254 }
Emeric Bruned760922010-10-22 17:59:25 +02001255 else if (!strcmp(args[0], "unix-bind")) {
1256 int cur_arg = 1;
1257 while (*(args[cur_arg])) {
1258 if (!strcmp(args[cur_arg], "prefix")) {
1259 if (global.unix_bind.prefix != NULL) {
1260 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1261 err_code |= ERR_ALERT;
1262 cur_arg += 2;
1263 continue;
1264 }
1265
1266 if (*(args[cur_arg+1]) == 0) {
1267 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1268 err_code |= ERR_ALERT | ERR_FATAL;
1269 goto out;
1270 }
1271 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1272 cur_arg += 2;
1273 continue;
1274 }
1275
1276 if (!strcmp(args[cur_arg], "mode")) {
1277
1278 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1279 cur_arg += 2;
1280 continue;
1281 }
1282
1283 if (!strcmp(args[cur_arg], "uid")) {
1284
1285 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1286 cur_arg += 2;
1287 continue;
1288 }
1289
1290 if (!strcmp(args[cur_arg], "gid")) {
1291
1292 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1293 cur_arg += 2;
1294 continue;
1295 }
1296
1297 if (!strcmp(args[cur_arg], "user")) {
1298 struct passwd *user;
1299
1300 user = getpwnam(args[cur_arg + 1]);
1301 if (!user) {
1302 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1303 file, linenum, args[0], args[cur_arg + 1 ]);
1304 err_code |= ERR_ALERT | ERR_FATAL;
1305 goto out;
1306 }
1307
1308 global.unix_bind.ux.uid = user->pw_uid;
1309 cur_arg += 2;
1310 continue;
1311 }
1312
1313 if (!strcmp(args[cur_arg], "group")) {
1314 struct group *group;
1315
1316 group = getgrnam(args[cur_arg + 1]);
1317 if (!group) {
1318 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1319 file, linenum, args[0], args[cur_arg + 1 ]);
1320 err_code |= ERR_ALERT | ERR_FATAL;
1321 goto out;
1322 }
1323
1324 global.unix_bind.ux.gid = group->gr_gid;
1325 cur_arg += 2;
1326 continue;
1327 }
1328
Willy Tarreaub48f9582011-09-05 01:17:06 +02001329 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001330 file, linenum, args[0]);
1331 err_code |= ERR_ALERT | ERR_FATAL;
1332 goto out;
1333 }
1334 }
William Lallemand0f99e342011-10-12 17:50:54 +02001335 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1336 /* delete previous herited or defined syslog servers */
1337 struct logsrv *back;
1338 struct logsrv *tmp;
1339
1340 if (*(args[1]) != 0) {
1341 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1342 err_code |= ERR_ALERT | ERR_FATAL;
1343 goto out;
1344 }
1345
1346 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1347 LIST_DEL(&tmp->list);
1348 free(tmp);
1349 }
1350 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001351 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001352 struct sockaddr_storage *sk;
1353 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001354 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001355 int arg = 0;
1356 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001357
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 if (*(args[1]) == 0 || *(args[2]) == 0) {
1359 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001360 err_code |= ERR_ALERT | ERR_FATAL;
1361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001362 }
William Lallemand0f99e342011-10-12 17:50:54 +02001363
1364 logsrv = calloc(1, sizeof(struct logsrv));
1365
Willy Tarreau18324f52014-06-27 18:10:07 +02001366 /* just after the address, a length may be specified */
1367 if (strcmp(args[arg+2], "len") == 0) {
1368 len = atoi(args[arg+3]);
1369 if (len < 80 || len > 65535) {
1370 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1371 file, linenum, args[arg+3]);
1372 err_code |= ERR_ALERT | ERR_FATAL;
1373 goto out;
1374 }
1375 logsrv->maxlen = len;
1376
1377 /* skip these two args */
1378 arg += 2;
1379 }
1380 else
1381 logsrv->maxlen = MAX_SYSLOG_LEN;
1382
1383 if (logsrv->maxlen > global.max_syslog_len) {
1384 global.max_syslog_len = logsrv->maxlen;
1385 logline = realloc(logline, global.max_syslog_len + 1);
1386 }
1387
1388 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001389 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001390 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001391 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001392 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001393 }
1394
William Lallemand0f99e342011-10-12 17:50:54 +02001395 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001396 if (*(args[arg+3])) {
1397 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001398 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001399 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001400 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001401 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001402 }
1403 }
1404
William Lallemand0f99e342011-10-12 17:50:54 +02001405 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001406 if (*(args[arg+4])) {
1407 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001408 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001409 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001410 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001411 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001412 }
1413 }
1414
Willy Tarreau902636f2013-03-10 19:44:48 +01001415 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001416 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001417 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001418 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001419 free(logsrv);
1420 goto out;
1421 }
1422 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001423
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001424 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001425 if (port1 != port2) {
1426 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1427 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001428 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001429 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001430 goto out;
1431 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001432
William Lallemand0f99e342011-10-12 17:50:54 +02001433 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001434 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001435 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001436 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001437
William Lallemand0f99e342011-10-12 17:50:54 +02001438 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001439 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001440 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1441 char *name;
1442 int len;
1443
1444 if (global.log_send_hostname != NULL) {
1445 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1446 err_code |= ERR_ALERT;
1447 goto out;
1448 }
1449
1450 if (*(args[1]))
1451 name = args[1];
1452 else
1453 name = hostname;
1454
1455 len = strlen(name);
1456
1457 /* We'll add a space after the name to respect the log format */
1458 free(global.log_send_hostname);
1459 global.log_send_hostname = malloc(len + 2);
1460 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1461 }
Kevinm48936af2010-12-22 16:08:21 +00001462 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1463 if (*(args[1]) == 0) {
1464 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1465 err_code |= ERR_ALERT | ERR_FATAL;
1466 goto out;
1467 }
1468 free(global.log_tag);
1469 global.log_tag = strdup(args[1]);
1470 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001471 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1472 if (global.spread_checks != 0) {
1473 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001474 err_code |= ERR_ALERT;
1475 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001476 }
1477 if (*(args[1]) == 0) {
1478 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001479 err_code |= ERR_ALERT | ERR_FATAL;
1480 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001481 }
1482 global.spread_checks = atol(args[1]);
1483 if (global.spread_checks < 0 || global.spread_checks > 50) {
1484 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001485 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001487 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001488 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1489 const char *err;
1490 unsigned int val;
1491
1492
1493 if (*(args[1]) == 0) {
1494 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1495 err_code |= ERR_ALERT | ERR_FATAL;
1496 goto out;
1497 }
1498
1499 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1500 if (err) {
1501 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1502 err_code |= ERR_ALERT | ERR_FATAL;
1503 }
1504 global.max_spread_checks = val;
1505 if (global.max_spread_checks < 0) {
1506 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1507 err_code |= ERR_ALERT | ERR_FATAL;
1508 }
1509 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001510 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1511#ifdef USE_CPU_AFFINITY
1512 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001513 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001514 unsigned long cpus = 0;
1515
1516 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001517 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001518 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001519 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001520 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001521 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001522 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001523 proc = atol(args[1]);
1524 if (proc >= 1 && proc <= LONGBITS)
1525 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001526 }
1527
1528 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001529 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",
1530 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001531 err_code |= ERR_ALERT | ERR_FATAL;
1532 goto out;
1533 }
1534
1535 cur_arg = 2;
1536 while (*args[cur_arg]) {
1537 unsigned int low, high;
1538
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001539 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001540 char *dash = strchr(args[cur_arg], '-');
1541
1542 low = high = str2uic(args[cur_arg]);
1543 if (dash)
1544 high = str2uic(dash + 1);
1545
1546 if (high < low) {
1547 unsigned int swap = low;
1548 low = high;
1549 high = swap;
1550 }
1551
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001552 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001553 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001554 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001555 err_code |= ERR_ALERT | ERR_FATAL;
1556 goto out;
1557 }
1558
1559 while (low <= high)
1560 cpus |= 1UL << low++;
1561 }
1562 else {
1563 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1564 file, linenum, args[0], args[cur_arg]);
1565 err_code |= ERR_ALERT | ERR_FATAL;
1566 goto out;
1567 }
1568 cur_arg++;
1569 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001570 for (i = 0; i < LONGBITS; i++)
1571 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001572 global.cpu_map[i] = cpus;
1573#else
1574 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1575 err_code |= ERR_ALERT | ERR_FATAL;
1576 goto out;
1577#endif
1578 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001580 struct cfg_kw_list *kwl;
1581 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001582 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001583
1584 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1585 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1586 if (kwl->kw[index].section != CFG_GLOBAL)
1587 continue;
1588 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001589 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001590 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001591 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001592 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001593 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001594 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001595 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001596 err_code |= ERR_WARN;
1597 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001598 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001599 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001600 }
1601 }
1602 }
1603
Willy Tarreaubaaee002006-06-26 02:48:02 +02001604 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001605 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001606 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001607
Willy Tarreau058e9072009-07-20 09:30:05 +02001608 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001609 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001610 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001611}
1612
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001613void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001614{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001615 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001616 defproxy.mode = PR_MODE_TCP;
1617 defproxy.state = PR_STNEW;
1618 defproxy.maxconn = cfg_maxpconn;
1619 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001620
Simon Horman66183002013-02-23 10:16:43 +09001621 defproxy.defsrv.check.inter = DEF_CHKINTR;
1622 defproxy.defsrv.check.fastinter = 0;
1623 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001624 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1625 defproxy.defsrv.agent.fastinter = 0;
1626 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001627 defproxy.defsrv.check.rise = DEF_RISETIME;
1628 defproxy.defsrv.check.fall = DEF_FALLTIME;
1629 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1630 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001631 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001632 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001633 defproxy.defsrv.maxqueue = 0;
1634 defproxy.defsrv.minconn = 0;
1635 defproxy.defsrv.maxconn = 0;
1636 defproxy.defsrv.slowstart = 0;
1637 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1638 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1639 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001640
1641 defproxy.email_alert.level = LOG_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001642}
1643
Willy Tarreauade5ec42010-01-28 19:33:49 +01001644
Willy Tarreau63af98d2014-05-18 08:11:41 +02001645/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1646 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1647 * ERR_FATAL in case of error.
1648 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001649static int create_cond_regex_rule(const char *file, int line,
1650 struct proxy *px, int dir, int action, int flags,
1651 const char *cmd, const char *reg, const char *repl,
1652 const char **cond_start)
1653{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001654 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001655 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001656 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001657 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001658 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001659 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001660 int cs;
1661 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001662
1663 if (px == &defproxy) {
1664 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001665 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001666 goto err;
1667 }
1668
1669 if (*reg == 0) {
1670 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001671 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001672 goto err;
1673 }
1674
1675 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001676 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001677
Willy Tarreau5321c422010-01-28 20:35:13 +01001678 if (cond_start &&
1679 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001680 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1681 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1682 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001683 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001684 goto err;
1685 }
1686 }
1687 else if (cond_start && **cond_start) {
1688 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1689 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001690 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001691 goto err;
1692 }
1693
Willy Tarreau63af98d2014-05-18 08:11:41 +02001694 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001695 (dir == SMP_OPT_DIR_REQ) ?
1696 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1697 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1698 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001699
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001700 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001701 if (!preg) {
1702 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001703 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001704 goto err;
1705 }
1706
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001707 cs = !(flags & REG_ICASE);
1708 cap = !(flags & REG_NOSUB);
1709 error = NULL;
1710 if (!regex_comp(reg, preg, cs, cap, &error)) {
1711 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1712 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001713 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001714 goto err;
1715 }
1716
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001717 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001718 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001719 if (repl && err) {
1720 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1721 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001722 ret_code |= ERR_ALERT | ERR_FATAL;
1723 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001724 }
1725
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001726 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001727 ret_code |= ERR_WARN;
1728
1729 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001730
Willy Tarreau63af98d2014-05-18 08:11:41 +02001731 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001732 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001733 err:
1734 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001735 free(errmsg);
1736 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001737}
1738
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001740 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001741 * Returns the error code, 0 if OK, or any combination of :
1742 * - ERR_ABORT: must abort ASAP
1743 * - ERR_FATAL: we can continue parsing but not start the service
1744 * - ERR_WARN: a warning has been emitted
1745 * - ERR_ALERT: an alert has been emitted
1746 * Only the two first ones can stop processing, the two others are just
1747 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001748 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001749int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1750{
1751 static struct peers *curpeers = NULL;
1752 struct peer *newpeer = NULL;
1753 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001754 struct bind_conf *bind_conf;
1755 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001756 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001757 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001758
1759 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001760 if (!*args[1]) {
1761 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001762 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001763 goto out;
1764 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001765
1766 err = invalid_char(args[1]);
1767 if (err) {
1768 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1769 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001770 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001771 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001772 }
1773
1774 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1775 /*
1776 * If there are two proxies with the same name only following
1777 * combinations are allowed:
1778 */
1779 if (strcmp(curpeers->id, args[1]) == 0) {
1780 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1781 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1782 err_code |= ERR_WARN;
1783 }
1784 }
1785
1786 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1787 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1788 err_code |= ERR_ALERT | ERR_ABORT;
1789 goto out;
1790 }
1791
1792 curpeers->next = peers;
1793 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001794 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001795 curpeers->conf.line = linenum;
1796 curpeers->last_change = now.tv_sec;
1797 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001798 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001799 }
1800 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001801 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001802 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001803 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001804
1805 if (!*args[2]) {
1806 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1807 file, linenum, args[0]);
1808 err_code |= ERR_ALERT | ERR_FATAL;
1809 goto out;
1810 }
1811
1812 err = invalid_char(args[1]);
1813 if (err) {
1814 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1815 file, linenum, *err, args[1]);
1816 err_code |= ERR_ALERT | ERR_FATAL;
1817 goto out;
1818 }
1819
1820 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1821 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1822 err_code |= ERR_ALERT | ERR_ABORT;
1823 goto out;
1824 }
1825
1826 /* the peers are linked backwards first */
1827 curpeers->count++;
1828 newpeer->next = curpeers->remote;
1829 curpeers->remote = newpeer;
1830 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001831 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001832 newpeer->conf.line = linenum;
1833
1834 newpeer->last_change = now.tv_sec;
1835 newpeer->id = strdup(args[1]);
1836
Willy Tarreau902636f2013-03-10 19:44:48 +01001837 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001838 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001839 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001840 err_code |= ERR_ALERT | ERR_FATAL;
1841 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001842 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001843
1844 proto = protocol_by_family(sk->ss_family);
1845 if (!proto || !proto->connect) {
1846 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1847 file, linenum, args[0], args[1]);
1848 err_code |= ERR_ALERT | ERR_FATAL;
1849 goto out;
1850 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001851
1852 if (port1 != port2) {
1853 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1854 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001855 err_code |= ERR_ALERT | ERR_FATAL;
1856 goto out;
1857 }
1858
Willy Tarreau2aa38802013-02-20 19:20:59 +01001859 if (!port1) {
1860 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1861 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001862 err_code |= ERR_ALERT | ERR_FATAL;
1863 goto out;
1864 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001865
Emeric Brun32da3c42010-09-23 18:39:19 +02001866 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001867 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001868 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001869 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001870
Emeric Brun32da3c42010-09-23 18:39:19 +02001871 if (strcmp(newpeer->id, localpeer) == 0) {
1872 /* Current is local peer, it define a frontend */
1873 newpeer->local = 1;
1874
1875 if (!curpeers->peers_fe) {
1876 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1877 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1878 err_code |= ERR_ALERT | ERR_ABORT;
1879 goto out;
1880 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001881
Willy Tarreau237250c2011-07-29 01:49:03 +02001882 init_new_proxy(curpeers->peers_fe);
1883 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001884 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001885 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1886 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01001887 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02001888
1889 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1890
Willy Tarreau902636f2013-03-10 19:44:48 +01001891 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1892 if (errmsg && *errmsg) {
1893 indent_msg(&errmsg, 2);
1894 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001895 }
1896 else
1897 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1898 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001899 err_code |= ERR_FATAL;
1900 goto out;
1901 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001902
1903 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001904 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001905 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1906 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02001907 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02001908 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001909 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01001910 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001911 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1912 global.maxsock += l->maxconn;
1913 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001914 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001915 else {
1916 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1917 file, linenum, args[0], args[1],
1918 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1919 err_code |= ERR_FATAL;
1920 goto out;
1921 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001922 }
1923 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001924 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
1925 curpeers->state = PR_STSTOPPED;
1926 }
1927 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
1928 curpeers->state = PR_STNEW;
1929 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001930 else if (*args[0] != 0) {
1931 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1932 err_code |= ERR_ALERT | ERR_FATAL;
1933 goto out;
1934 }
1935
1936out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001937 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001938 return err_code;
1939}
1940
Simon Horman0d16a402015-01-30 11:22:58 +09001941
1942/*
1943 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
1944 * Returns the error code, 0 if OK, or any combination of :
1945 * - ERR_ABORT: must abort ASAP
1946 * - ERR_FATAL: we can continue parsing but not start the service
1947 * - ERR_WARN: a warning has been emitted
1948 * - ERR_ALERT: an alert has been emitted
1949 * Only the two first ones can stop processing, the two others are just
1950 * indicators.
1951 */
1952int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
1953{
1954 static struct mailers *curmailers = NULL;
1955 struct mailer *newmailer = NULL;
1956 const char *err;
1957 int err_code = 0;
1958 char *errmsg = NULL;
1959
1960 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
1961 if (!*args[1]) {
1962 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
1963 err_code |= ERR_ALERT | ERR_ABORT;
1964 goto out;
1965 }
1966
1967 err = invalid_char(args[1]);
1968 if (err) {
1969 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1970 file, linenum, *err, args[0], args[1]);
1971 err_code |= ERR_ALERT | ERR_ABORT;
1972 goto out;
1973 }
1974
1975 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
1976 /*
1977 * If there are two proxies with the same name only following
1978 * combinations are allowed:
1979 */
1980 if (strcmp(curmailers->id, args[1]) == 0) {
1981 Warning("Parsing [%s:%d]: mailers '%s' has same name as another mailers (declared at %s:%d).\n",
1982 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
1983 err_code |= ERR_WARN;
1984 }
1985 }
1986
1987 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
1988 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1989 err_code |= ERR_ALERT | ERR_ABORT;
1990 goto out;
1991 }
1992
1993 curmailers->next = mailers;
1994 mailers = curmailers;
1995 curmailers->conf.file = strdup(file);
1996 curmailers->conf.line = linenum;
1997 curmailers->id = strdup(args[1]);
1998 }
1999 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2000 struct sockaddr_storage *sk;
2001 int port1, port2;
2002 struct protocol *proto;
2003
2004 if (!*args[2]) {
2005 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2006 file, linenum, args[0]);
2007 err_code |= ERR_ALERT | ERR_FATAL;
2008 goto out;
2009 }
2010
2011 err = invalid_char(args[1]);
2012 if (err) {
2013 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2014 file, linenum, *err, args[1]);
2015 err_code |= ERR_ALERT | ERR_FATAL;
2016 goto out;
2017 }
2018
2019 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2020 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2021 err_code |= ERR_ALERT | ERR_ABORT;
2022 goto out;
2023 }
2024
2025 /* the mailers are linked backwards first */
2026 curmailers->count++;
2027 newmailer->next = curmailers->mailer_list;
2028 curmailers->mailer_list = newmailer;
2029 newmailer->mailers = curmailers;
2030 newmailer->conf.file = strdup(file);
2031 newmailer->conf.line = linenum;
2032
2033 newmailer->id = strdup(args[1]);
2034
2035 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2036 if (!sk) {
2037 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2038 err_code |= ERR_ALERT | ERR_FATAL;
2039 goto out;
2040 }
2041
2042 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002043 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2044 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002045 file, linenum, args[0], args[1]);
2046 err_code |= ERR_ALERT | ERR_FATAL;
2047 goto out;
2048 }
2049
2050 if (port1 != port2) {
2051 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2052 file, linenum, args[0], args[1], args[2]);
2053 err_code |= ERR_ALERT | ERR_FATAL;
2054 goto out;
2055 }
2056
2057 if (!port1) {
2058 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2059 file, linenum, args[0], args[1], args[2]);
2060 err_code |= ERR_ALERT | ERR_FATAL;
2061 goto out;
2062 }
2063
2064 newmailer->addr = *sk;
2065 newmailer->proto = proto;
2066 newmailer->xprt = &raw_sock;
2067 newmailer->sock_init_arg = NULL;
2068 } /* neither "mailer" nor "mailers" */
2069 else if (*args[0] != 0) {
2070 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2071 err_code |= ERR_ALERT | ERR_FATAL;
2072 goto out;
2073 }
2074
2075out:
2076 free(errmsg);
2077 return err_code;
2078}
2079
Simon Horman9dc49962015-01-30 11:22:59 +09002080static void free_email_alert(struct proxy *p)
2081{
2082 free(p->email_alert.mailers.name);
2083 p->email_alert.mailers.name = NULL;
2084 free(p->email_alert.from);
2085 p->email_alert.from = NULL;
2086 free(p->email_alert.to);
2087 p->email_alert.to = NULL;
2088 free(p->email_alert.myhostname);
2089 p->email_alert.myhostname = NULL;
2090}
2091
Willy Tarreau3842f002009-06-14 11:39:52 +02002092int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002093{
2094 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002095 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002096 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002097 int rc;
2098 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002099 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002100 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002101 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002102 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002103 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104
Willy Tarreau977b8e42006-12-29 14:19:17 +01002105 if (!strcmp(args[0], "listen"))
2106 rc = PR_CAP_LISTEN;
2107 else if (!strcmp(args[0], "frontend"))
2108 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002109 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002110 rc = PR_CAP_BE | PR_CAP_RS;
2111 else if (!strcmp(args[0], "ruleset"))
2112 rc = PR_CAP_RS;
2113 else
2114 rc = PR_CAP_NONE;
2115
2116 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002117 struct ebpt_node *node;
2118
Willy Tarreaubaaee002006-06-26 02:48:02 +02002119 if (!*args[1]) {
2120 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2121 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2122 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002123 err_code |= ERR_ALERT | ERR_ABORT;
2124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002125 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002126
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002127 err = invalid_char(args[1]);
2128 if (err) {
2129 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2130 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002131 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002132 }
2133
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002134 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
2135 curproxy = container_of(node, struct proxy, conf.by_name);
2136
2137 if (strcmp(curproxy->id, args[1]) != 0)
2138 break;
2139
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002140 /*
2141 * If there are two proxies with the same name only following
2142 * combinations are allowed:
2143 *
2144 * listen backend frontend ruleset
2145 * listen - - - -
2146 * backend - - OK -
2147 * frontend - OK - -
2148 * ruleset - - - -
2149 */
2150
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002151 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
2152 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02002153 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
2154 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2155 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02002156 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002157 }
2158 }
2159
Willy Tarreaubaaee002006-06-26 02:48:02 +02002160 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2161 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002162 err_code |= ERR_ALERT | ERR_ABORT;
2163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002164 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002165
Willy Tarreau97cb7802010-01-03 20:23:58 +01002166 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002167 curproxy->next = proxy;
2168 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002169 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2170 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002171 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002172 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002173 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002174 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002175
2176 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002177 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002178 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02002179
Willy Tarreau4348fad2012-09-20 16:48:07 +02002180 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2181
Willy Tarreau902636f2013-03-10 19:44:48 +01002182 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2183 if (errmsg && *errmsg) {
2184 indent_msg(&errmsg, 2);
2185 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002186 }
2187 else
2188 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2189 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002190 err_code |= ERR_FATAL;
2191 goto out;
2192 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002193
Willy Tarreau4348fad2012-09-20 16:48:07 +02002194 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002195 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002197 }
2198
2199 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002200 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002201 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002202
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002205 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002206 curproxy->no_options = defproxy.no_options;
2207 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002208 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002209 curproxy->except_net = defproxy.except_net;
2210 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002211 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002212 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002213
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002214 if (defproxy.fwdfor_hdr_len) {
2215 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2216 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2217 }
2218
Willy Tarreaub86db342009-11-30 11:50:16 +01002219 if (defproxy.orgto_hdr_len) {
2220 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2221 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2222 }
2223
Mark Lamourinec2247f02012-01-04 13:02:01 -05002224 if (defproxy.server_id_hdr_len) {
2225 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2226 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2227 }
2228
Willy Tarreau977b8e42006-12-29 14:19:17 +01002229 if (curproxy->cap & PR_CAP_FE) {
2230 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002231 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002232 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002233
2234 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002235 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2236 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002237
2238 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240
Willy Tarreau977b8e42006-12-29 14:19:17 +01002241 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002242 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002243 curproxy->fullconn = defproxy.fullconn;
2244 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002245 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002246
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002247 if (defproxy.check_req) {
2248 curproxy->check_req = calloc(1, defproxy.check_len);
2249 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2250 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002251 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002252
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002253 if (defproxy.expect_str) {
2254 curproxy->expect_str = strdup(defproxy.expect_str);
2255 if (defproxy.expect_regex) {
2256 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002257 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2258 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002259 }
2260 }
2261
Willy Tarreau67402132012-05-31 20:40:20 +02002262 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002263 if (defproxy.cookie_name)
2264 curproxy->cookie_name = strdup(defproxy.cookie_name);
2265 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002266 if (defproxy.cookie_domain)
2267 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002268
Willy Tarreau31936852010-10-06 16:59:56 +02002269 if (defproxy.cookie_maxidle)
2270 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2271
2272 if (defproxy.cookie_maxlife)
2273 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2274
Emeric Brun647caf12009-06-30 17:57:00 +02002275 if (defproxy.rdp_cookie_name)
2276 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2277 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2278
Willy Tarreau01732802007-11-01 22:48:15 +01002279 if (defproxy.url_param_name)
2280 curproxy->url_param_name = strdup(defproxy.url_param_name);
2281 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002282
Benoitaffb4812009-03-25 13:02:10 +01002283 if (defproxy.hh_name)
2284 curproxy->hh_name = strdup(defproxy.hh_name);
2285 curproxy->hh_len = defproxy.hh_len;
2286 curproxy->hh_match_domain = defproxy.hh_match_domain;
2287
Willy Tarreauef9a3602012-12-08 22:29:20 +01002288 if (defproxy.conn_src.iface_name)
2289 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2290 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002291 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002292#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002293 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002294#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002295 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002296
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002297 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002298 if (defproxy.capture_name)
2299 curproxy->capture_name = strdup(defproxy.capture_name);
2300 curproxy->capture_namelen = defproxy.capture_namelen;
2301 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002302 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002303
Willy Tarreau977b8e42006-12-29 14:19:17 +01002304 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002305 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002306 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002307 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002308 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002309 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002310 curproxy->mon_net = defproxy.mon_net;
2311 curproxy->mon_mask = defproxy.mon_mask;
2312 if (defproxy.monitor_uri)
2313 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2314 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002315 if (defproxy.defbe.name)
2316 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002317
2318 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002319 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2320 if (curproxy->conf.logformat_string &&
2321 curproxy->conf.logformat_string != default_http_log_format &&
2322 curproxy->conf.logformat_string != default_tcp_log_format &&
2323 curproxy->conf.logformat_string != clf_http_log_format)
2324 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2325
2326 if (defproxy.conf.lfs_file) {
2327 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2328 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2329 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002330 }
2331
2332 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002333 curproxy->timeout.connect = defproxy.timeout.connect;
2334 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002335 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002336 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002337 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002338 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002339 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002340 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002341 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002342 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002343 }
2344
Willy Tarreaubaaee002006-06-26 02:48:02 +02002345 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002346 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002347
2348 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002349 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002350 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002351 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002352 LIST_INIT(&node->list);
2353 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2354 }
2355
Willy Tarreau62a61232013-04-12 18:13:46 +02002356 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2357 if (curproxy->conf.uniqueid_format_string)
2358 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2359
Willy Tarreau094af4e2015-01-07 15:03:42 +01002360 if (defproxy.log_tag)
2361 curproxy->log_tag = strdup(defproxy.log_tag);
2362
Willy Tarreau62a61232013-04-12 18:13:46 +02002363 if (defproxy.conf.uif_file) {
2364 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2365 curproxy->conf.uif_line = defproxy.conf.uif_line;
2366 }
William Lallemanda73203e2012-03-12 12:48:57 +01002367
2368 /* copy default header unique id */
2369 if (defproxy.header_unique_id)
2370 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2371
William Lallemand82fe75c2012-10-23 10:25:10 +02002372 /* default compression options */
2373 if (defproxy.comp != NULL) {
2374 curproxy->comp = calloc(1, sizeof(struct comp));
2375 curproxy->comp->algos = defproxy.comp->algos;
2376 curproxy->comp->types = defproxy.comp->types;
2377 }
2378
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002380 curproxy->conf.used_listener_id = EB_ROOT;
2381 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002382
Simon Horman98637e52014-06-20 12:30:16 +09002383 if (defproxy.check_path)
2384 curproxy->check_path = strdup(defproxy.check_path);
2385 if (defproxy.check_command)
2386 curproxy->check_command = strdup(defproxy.check_command);
2387
Simon Horman9dc49962015-01-30 11:22:59 +09002388 if (defproxy.email_alert.mailers.name)
2389 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2390 if (defproxy.email_alert.from)
2391 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2392 if (defproxy.email_alert.to)
2393 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2394 if (defproxy.email_alert.myhostname)
2395 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002396 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002397
Willy Tarreau93893792009-07-23 13:19:11 +02002398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 }
2400 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2401 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002402 /* FIXME-20070101: we should do this too at the end of the
2403 * config parsing to free all default values.
2404 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002405 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002406 free(defproxy.check_command);
2407 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002408 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002409 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002410 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002411 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002412 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002413 free(defproxy.capture_name);
2414 free(defproxy.monitor_uri);
2415 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002416 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002417 free(defproxy.fwdfor_hdr_name);
2418 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002419 free(defproxy.orgto_hdr_name);
2420 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002421 free(defproxy.server_id_hdr_name);
2422 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002423 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002424 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002425 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002426 free(defproxy.expect_regex);
2427 defproxy.expect_regex = NULL;
2428 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002429
Willy Tarreau62a61232013-04-12 18:13:46 +02002430 if (defproxy.conf.logformat_string != default_http_log_format &&
2431 defproxy.conf.logformat_string != default_tcp_log_format &&
2432 defproxy.conf.logformat_string != clf_http_log_format)
2433 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002434
Willy Tarreau62a61232013-04-12 18:13:46 +02002435 free(defproxy.conf.uniqueid_format_string);
2436 free(defproxy.conf.lfs_file);
2437 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002438 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002439 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002440
Willy Tarreaua534fea2008-08-03 12:19:50 +02002441 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002442 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002443
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 /* we cannot free uri_auth because it might already be used */
2445 init_default_instance();
2446 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002447 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2448 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002449 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451 }
2452 else if (curproxy == NULL) {
2453 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002456 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002457
2458 /* update the current file and line being parsed */
2459 curproxy->conf.args.file = curproxy->conf.file;
2460 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002461
2462 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002463 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2464 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2465 if (err_code & ERR_FATAL)
2466 goto out;
2467 }
2468 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002469 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002470 int cur_arg;
2471
Willy Tarreaubaaee002006-06-26 02:48:02 +02002472 if (curproxy == &defproxy) {
2473 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002474 err_code |= ERR_ALERT | ERR_FATAL;
2475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002476 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002477 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002478 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002479
Willy Tarreau24709282013-03-10 21:32:12 +01002480 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002481 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002482 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002486
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002487 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002488
2489 /* use default settings for unix sockets */
2490 bind_conf->ux.uid = global.unix_bind.ux.uid;
2491 bind_conf->ux.gid = global.unix_bind.ux.gid;
2492 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002493
2494 /* NOTE: the following line might create several listeners if there
2495 * are comma-separated IPs or port ranges. So all further processing
2496 * will have to be applied to all listeners created after last_listen.
2497 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002498 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2499 if (errmsg && *errmsg) {
2500 indent_msg(&errmsg, 2);
2501 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002502 }
2503 else
2504 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2505 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002506 err_code |= ERR_ALERT | ERR_FATAL;
2507 goto out;
2508 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002509
Willy Tarreau4348fad2012-09-20 16:48:07 +02002510 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2511 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002512 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002513 }
2514
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002515 cur_arg = 2;
2516 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002517 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002518 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002519 char *err;
2520
Willy Tarreau26982662012-09-12 23:17:10 +02002521 kw = bind_find_kw(args[cur_arg]);
2522 if (kw) {
2523 char *err = NULL;
2524 int code;
2525
2526 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002527 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2528 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002529 cur_arg += 1 + kw->skip ;
2530 err_code |= ERR_ALERT | ERR_FATAL;
2531 goto out;
2532 }
2533
Willy Tarreau4348fad2012-09-20 16:48:07 +02002534 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002535 err_code |= code;
2536
2537 if (code) {
2538 if (err && *err) {
2539 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002540 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002541 }
2542 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002543 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2544 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002545 if (code & ERR_FATAL) {
2546 free(err);
2547 cur_arg += 1 + kw->skip;
2548 goto out;
2549 }
2550 }
2551 free(err);
2552 cur_arg += 1 + kw->skip;
2553 continue;
2554 }
2555
Willy Tarreau8638f482012-09-18 18:01:17 +02002556 err = NULL;
2557 if (!bind_dumped) {
2558 bind_dump_kws(&err);
2559 indent_msg(&err, 4);
2560 bind_dumped = 1;
2561 }
2562
2563 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2564 file, linenum, args[0], args[1], args[cur_arg],
2565 err ? " Registered keywords :" : "", err ? err : "");
2566 free(err);
2567
Willy Tarreau93893792009-07-23 13:19:11 +02002568 err_code |= ERR_ALERT | ERR_FATAL;
2569 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002570 }
Willy Tarreau93893792009-07-23 13:19:11 +02002571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 }
2573 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002574 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2576 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002577 err_code |= ERR_ALERT | ERR_FATAL;
2578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002580 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002581 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002582
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583 /* flush useless bits */
2584 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002587 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002588 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002589 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002590
Willy Tarreau1c47f852006-07-09 08:22:27 +02002591 if (!*args[1]) {
2592 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2593 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_ALERT | ERR_FATAL;
2595 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002596 }
2597
Willy Tarreaua534fea2008-08-03 12:19:50 +02002598 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002599 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002600 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002601 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002602 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2603
Willy Tarreau93893792009-07-23 13:19:11 +02002604 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002605 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002606 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2607 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2608 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2609 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2610 else {
2611 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002612 err_code |= ERR_ALERT | ERR_FATAL;
2613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 }
2615 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002616 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002617 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002618
2619 if (curproxy == &defproxy) {
2620 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2621 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002624 }
2625
2626 if (!*args[1]) {
2627 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2628 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002629 err_code |= ERR_ALERT | ERR_FATAL;
2630 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002631 }
2632
2633 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002634 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002635
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002636 if (curproxy->uuid <= 0) {
2637 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002638 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002639 err_code |= ERR_ALERT | ERR_FATAL;
2640 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002641 }
2642
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002643 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2644 if (node) {
2645 struct proxy *target = container_of(node, struct proxy, conf.id);
2646 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2647 file, linenum, proxy_type_str(curproxy), curproxy->id,
2648 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2649 err_code |= ERR_ALERT | ERR_FATAL;
2650 goto out;
2651 }
2652 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002653 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002654 else if (!strcmp(args[0], "description")) {
2655 int i, len=0;
2656 char *d;
2657
Cyril Bonté99ed3272010-01-24 23:29:44 +01002658 if (curproxy == &defproxy) {
2659 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2660 file, linenum, args[0]);
2661 err_code |= ERR_ALERT | ERR_FATAL;
2662 goto out;
2663 }
2664
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002665 if (!*args[1]) {
2666 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2667 file, linenum, args[0]);
2668 return -1;
2669 }
2670
Willy Tarreau348acfe2014-04-14 15:00:39 +02002671 for (i = 1; *args[i]; i++)
2672 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002673
2674 d = (char *)calloc(1, len);
2675 curproxy->desc = d;
2676
Willy Tarreau348acfe2014-04-14 15:00:39 +02002677 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2678 for (i = 2; *args[i]; i++)
2679 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002680
2681 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002682 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2683 curproxy->state = PR_STSTOPPED;
2684 }
2685 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2686 curproxy->state = PR_STNEW;
2687 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002688 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2689 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002690 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002691
2692 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002693 unsigned int low, high;
2694
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002695 if (strcmp(args[cur_arg], "all") == 0) {
2696 set = 0;
2697 break;
2698 }
2699 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002700 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002701 }
2702 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002703 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002704 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002705 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002706 char *dash = strchr(args[cur_arg], '-');
2707
2708 low = high = str2uic(args[cur_arg]);
2709 if (dash)
2710 high = str2uic(dash + 1);
2711
2712 if (high < low) {
2713 unsigned int swap = low;
2714 low = high;
2715 high = swap;
2716 }
2717
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002718 if (low < 1 || high > LONGBITS) {
2719 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2720 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002721 err_code |= ERR_ALERT | ERR_FATAL;
2722 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002723 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002724 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002725 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002726 }
2727 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002728 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2729 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002730 err_code |= ERR_ALERT | ERR_FATAL;
2731 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002732 }
2733 cur_arg++;
2734 }
2735 curproxy->bind_proc = set;
2736 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002737 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002738 if (curproxy == &defproxy) {
2739 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002740 err_code |= ERR_ALERT | ERR_FATAL;
2741 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002742 }
2743
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002744 err = invalid_char(args[1]);
2745 if (err) {
2746 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2747 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002748 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002749 }
2750
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002751 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002752 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2753 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002756 }
2757 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002758 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2759 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002760
Willy Tarreau977b8e42006-12-29 14:19:17 +01002761 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002762 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002763
Willy Tarreaubaaee002006-06-26 02:48:02 +02002764 if (*(args[1]) == 0) {
2765 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2766 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002767 err_code |= ERR_ALERT | ERR_FATAL;
2768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002769 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002770
Willy Tarreau67402132012-05-31 20:40:20 +02002771 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002772 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002773 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002774 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002775 curproxy->cookie_name = strdup(args[1]);
2776 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002777
Willy Tarreaubaaee002006-06-26 02:48:02 +02002778 cur_arg = 2;
2779 while (*(args[cur_arg])) {
2780 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002781 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782 }
2783 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002784 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002785 }
2786 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002787 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002788 }
2789 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002790 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002791 }
2792 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002793 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002794 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002795 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002796 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002797 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002798 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002799 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002800 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002801 else if (!strcmp(args[cur_arg], "httponly")) {
2802 curproxy->ck_opts |= PR_CK_HTTPONLY;
2803 }
2804 else if (!strcmp(args[cur_arg], "secure")) {
2805 curproxy->ck_opts |= PR_CK_SECURE;
2806 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002807 else if (!strcmp(args[cur_arg], "domain")) {
2808 if (!*args[cur_arg + 1]) {
2809 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2810 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002811 err_code |= ERR_ALERT | ERR_FATAL;
2812 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002813 }
2814
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002815 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002816 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002817 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2818 " dots nor does not start with a dot."
2819 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002820 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002821 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002822 }
2823
2824 err = invalid_domainchar(args[cur_arg + 1]);
2825 if (err) {
2826 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2827 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002828 err_code |= ERR_ALERT | ERR_FATAL;
2829 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002830 }
2831
Willy Tarreau68a897b2009-12-03 23:28:34 +01002832 if (!curproxy->cookie_domain) {
2833 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2834 } else {
2835 /* one domain was already specified, add another one by
2836 * building the string which will be returned along with
2837 * the cookie.
2838 */
2839 char *new_ptr;
2840 int new_len = strlen(curproxy->cookie_domain) +
2841 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2842 new_ptr = malloc(new_len);
2843 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2844 free(curproxy->cookie_domain);
2845 curproxy->cookie_domain = new_ptr;
2846 }
Willy Tarreau31936852010-10-06 16:59:56 +02002847 cur_arg++;
2848 }
2849 else if (!strcmp(args[cur_arg], "maxidle")) {
2850 unsigned int maxidle;
2851 const char *res;
2852
2853 if (!*args[cur_arg + 1]) {
2854 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2855 file, linenum, args[cur_arg]);
2856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
2858 }
2859
2860 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2861 if (res) {
2862 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2863 file, linenum, *res, args[cur_arg]);
2864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
2866 }
2867 curproxy->cookie_maxidle = maxidle;
2868 cur_arg++;
2869 }
2870 else if (!strcmp(args[cur_arg], "maxlife")) {
2871 unsigned int maxlife;
2872 const char *res;
2873
2874 if (!*args[cur_arg + 1]) {
2875 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2876 file, linenum, args[cur_arg]);
2877 err_code |= ERR_ALERT | ERR_FATAL;
2878 goto out;
2879 }
2880
2881 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2882 if (res) {
2883 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2884 file, linenum, *res, args[cur_arg]);
2885 err_code |= ERR_ALERT | ERR_FATAL;
2886 goto out;
2887 }
2888 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002889 cur_arg++;
2890 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002891 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002892 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 +02002893 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896 }
2897 cur_arg++;
2898 }
Willy Tarreau67402132012-05-31 20:40:20 +02002899 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002900 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2901 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002902 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002903 }
2904
Willy Tarreau67402132012-05-31 20:40:20 +02002905 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002906 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2907 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002908 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002909 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002910
Willy Tarreau67402132012-05-31 20:40:20 +02002911 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002912 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2913 file, linenum);
2914 err_code |= ERR_ALERT | ERR_FATAL;
2915 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09002917 else if (!strcmp(args[0], "email-alert")) {
2918 if (*(args[1]) == 0) {
2919 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2920 file, linenum, args[0]);
2921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
2923 }
2924
2925 if (!strcmp(args[1], "from")) {
2926 if (*(args[1]) == 0) {
2927 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2928 file, linenum, args[1]);
2929 err_code |= ERR_ALERT | ERR_FATAL;
2930 goto out;
2931 }
2932 free(curproxy->email_alert.from);
2933 curproxy->email_alert.from = strdup(args[2]);
2934 }
2935 else if (!strcmp(args[1], "mailers")) {
2936 if (*(args[1]) == 0) {
2937 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2938 file, linenum, args[1]);
2939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
2941 }
2942 free(curproxy->email_alert.mailers.name);
2943 curproxy->email_alert.mailers.name = strdup(args[2]);
2944 }
2945 else if (!strcmp(args[1], "myhostname")) {
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.myhostname);
2953 curproxy->email_alert.myhostname = strdup(args[2]);
2954 }
Simon Horman64e34162015-02-06 11:11:57 +09002955 else if (!strcmp(args[1], "level")) {
2956 curproxy->email_alert.level = get_log_level(args[2]);
2957 if (curproxy->email_alert.level < 0) {
2958 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
2959 file, linenum, args[1], args[2]);
2960 err_code |= ERR_ALERT | ERR_FATAL;
2961 goto out;
2962 }
2963 }
Simon Horman9dc49962015-01-30 11:22:59 +09002964 else if (!strcmp(args[1], "to")) {
2965 if (*(args[1]) == 0) {
2966 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2967 file, linenum, args[1]);
2968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
2970 }
2971 free(curproxy->email_alert.to);
2972 curproxy->email_alert.to = strdup(args[2]);
2973 }
2974 else {
2975 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
2976 file, linenum, args[1]);
2977 err_code |= ERR_ALERT | ERR_FATAL;
2978 goto out;
2979 }
Simon Horman64e34162015-02-06 11:11:57 +09002980 /* Indicate that the email_alert is at least partially configured */
2981 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09002982 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09002983 else if (!strcmp(args[0], "external-check")) {
2984 if (*(args[1]) == 0) {
2985 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2986 file, linenum, args[0]);
2987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
2989 }
2990
2991 if (!strcmp(args[1], "command")) {
2992 if (*(args[1]) == 0) {
2993 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2994 file, linenum, args[1]);
2995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
2997 }
2998 free(curproxy->check_command);
2999 curproxy->check_command = strdup(args[2]);
3000 }
3001 else if (!strcmp(args[1], "path")) {
3002 if (*(args[1]) == 0) {
3003 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3004 file, linenum, args[1]);
3005 err_code |= ERR_ALERT | ERR_FATAL;
3006 goto out;
3007 }
3008 free(curproxy->check_path);
3009 curproxy->check_path = strdup(args[2]);
3010 }
3011 else {
3012 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3013 file, linenum, args[1]);
3014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
3016 }
3017 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003018 else if (!strcmp(args[0], "persist")) { /* persist */
3019 if (*(args[1]) == 0) {
3020 Alert("parsing [%s:%d] : missing persist method.\n",
3021 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003024 }
3025
3026 if (!strncmp(args[1], "rdp-cookie", 10)) {
3027 curproxy->options2 |= PR_O2_RDPC_PRST;
3028
Emeric Brunb982a3d2010-01-04 15:45:53 +01003029 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003030 const char *beg, *end;
3031
3032 beg = args[1] + 11;
3033 end = strchr(beg, ')');
3034
3035 if (!end || end == beg) {
3036 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3037 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003038 err_code |= ERR_ALERT | ERR_FATAL;
3039 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003040 }
3041
3042 free(curproxy->rdp_cookie_name);
3043 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3044 curproxy->rdp_cookie_len = end-beg;
3045 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003046 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003047 free(curproxy->rdp_cookie_name);
3048 curproxy->rdp_cookie_name = strdup("msts");
3049 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3050 }
3051 else { /* syntax */
3052 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3053 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003056 }
3057 }
3058 else {
3059 Alert("parsing [%s:%d] : unknown persist method.\n",
3060 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003063 }
3064 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003065 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003066 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003068 if (curproxy == &defproxy) {
3069 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3070 err_code |= ERR_ALERT | ERR_FATAL;
3071 goto out;
3072 }
3073
Willy Tarreau977b8e42006-12-29 14:19:17 +01003074 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003075 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003076
Willy Tarreaubaaee002006-06-26 02:48:02 +02003077 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003078 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003079 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003080 err_code |= ERR_ALERT | ERR_FATAL;
3081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082 }
3083 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003084 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085 curproxy->appsession_name = strdup(args[1]);
3086 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3087 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003088 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3089 if (err) {
3090 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3091 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003092 err_code |= ERR_ALERT | ERR_FATAL;
3093 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003094 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003095 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003096
Willy Tarreau51041c72007-09-09 21:56:53 +02003097 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3098 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003099 err_code |= ERR_ALERT | ERR_ABORT;
3100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003101 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003102
3103 cur_arg = 6;
3104 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003105 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3106 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003107 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003108 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003109 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003110 } else if (!strcmp(args[cur_arg], "prefix")) {
3111 curproxy->options2 |= PR_O2_AS_PFX;
3112 } else if (!strcmp(args[cur_arg], "mode")) {
3113 if (!*args[cur_arg + 1]) {
3114 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3115 file, linenum, args[0], args[cur_arg]);
3116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
3118 }
3119
3120 cur_arg++;
3121 if (!strcmp(args[cur_arg], "query-string")) {
3122 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3123 curproxy->options2 |= PR_O2_AS_M_QS;
3124 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3125 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3126 curproxy->options2 |= PR_O2_AS_M_PP;
3127 } else {
3128 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3129 err_code |= ERR_ALERT | ERR_FATAL;
3130 goto out;
3131 }
3132 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003133 cur_arg++;
3134 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 } /* Url App Session */
3136 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003137 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003138 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003139
Willy Tarreaubaaee002006-06-26 02:48:02 +02003140 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003141 if (curproxy == &defproxy) {
3142 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3143 err_code |= ERR_ALERT | ERR_FATAL;
3144 goto out;
3145 }
3146
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 if (*(args[4]) == 0) {
3148 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3149 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003150 err_code |= ERR_ALERT | ERR_FATAL;
3151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003152 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003153 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 curproxy->capture_name = strdup(args[2]);
3155 curproxy->capture_namelen = strlen(curproxy->capture_name);
3156 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003157 curproxy->to_log |= LW_COOKIE;
3158 }
3159 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3160 struct cap_hdr *hdr;
3161
3162 if (curproxy == &defproxy) {
3163 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 +02003164 err_code |= ERR_ALERT | ERR_FATAL;
3165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003166 }
3167
3168 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3169 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3170 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 hdr = calloc(sizeof(struct cap_hdr), 1);
3176 hdr->next = curproxy->req_cap;
3177 hdr->name = strdup(args[3]);
3178 hdr->namelen = strlen(args[3]);
3179 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003180 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 hdr->index = curproxy->nb_req_cap++;
3182 curproxy->req_cap = hdr;
3183 curproxy->to_log |= LW_REQHDR;
3184 }
3185 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3186 struct cap_hdr *hdr;
3187
3188 if (curproxy == &defproxy) {
3189 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 +02003190 err_code |= ERR_ALERT | ERR_FATAL;
3191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 }
3193
3194 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3195 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3196 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 }
3200 hdr = calloc(sizeof(struct cap_hdr), 1);
3201 hdr->next = curproxy->rsp_cap;
3202 hdr->name = strdup(args[3]);
3203 hdr->namelen = strlen(args[3]);
3204 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003205 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003206 hdr->index = curproxy->nb_rsp_cap++;
3207 curproxy->rsp_cap = hdr;
3208 curproxy->to_log |= LW_RSPHDR;
3209 }
3210 else {
3211 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3212 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003213 err_code |= ERR_ALERT | ERR_FATAL;
3214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215 }
3216 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003218 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003219 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003220
Willy Tarreaubaaee002006-06-26 02:48:02 +02003221 if (*(args[1]) == 0) {
3222 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3223 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003224 err_code |= ERR_ALERT | ERR_FATAL;
3225 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003226 }
3227 curproxy->conn_retries = atol(args[1]);
3228 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003229 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003230 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003231
3232 if (curproxy == &defproxy) {
3233 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
3236 }
3237
Willy Tarreau20b0de52012-12-24 15:45:22 +01003238 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3239 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3240 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3241 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003242 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003243 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3244 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 +01003245 file, linenum, args[0]);
3246 err_code |= ERR_WARN;
3247 }
3248
Willy Tarreauff011f22011-01-06 17:51:27 +01003249 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003250
Willy Tarreauff011f22011-01-06 17:51:27 +01003251 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003252 err_code |= ERR_ALERT | ERR_ABORT;
3253 goto out;
3254 }
3255
Willy Tarreau5002f572014-04-23 01:32:02 +02003256 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003257 err_code |= warnif_cond_conflicts(rule->cond,
3258 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3259 file, linenum);
3260
Willy Tarreauff011f22011-01-06 17:51:27 +01003261 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003262 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003263 else if (!strcmp(args[0], "http-response")) { /* response access control */
3264 struct http_res_rule *rule;
3265
3266 if (curproxy == &defproxy) {
3267 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3268 err_code |= ERR_ALERT | ERR_FATAL;
3269 goto out;
3270 }
3271
3272 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3273 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3274 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3275 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3276 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3277 file, linenum, args[0]);
3278 err_code |= ERR_WARN;
3279 }
3280
3281 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3282
3283 if (!rule) {
3284 err_code |= ERR_ALERT | ERR_ABORT;
3285 goto out;
3286 }
3287
3288 err_code |= warnif_cond_conflicts(rule->cond,
3289 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3290 file, linenum);
3291
3292 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3293 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003294 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3295 /* set the header name and length into the proxy structure */
3296 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3297 err_code |= ERR_WARN;
3298
3299 if (!*args[1]) {
3300 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3301 file, linenum, args[0]);
3302 err_code |= ERR_ALERT | ERR_FATAL;
3303 goto out;
3304 }
3305
3306 /* set the desired header name */
3307 free(curproxy->server_id_hdr_name);
3308 curproxy->server_id_hdr_name = strdup(args[1]);
3309 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3310 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003311 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003312 struct http_req_rule *rule;
3313
Willy Tarreaub099aca2008-10-12 17:26:37 +02003314 if (curproxy == &defproxy) {
3315 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003316 err_code |= ERR_ALERT | ERR_FATAL;
3317 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003318 }
3319
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003320 /* emulate "block" using "http-request block". Since these rules are supposed to
3321 * be processed before all http-request rules, we put them into their own list
3322 * and will insert them at the end.
3323 */
3324 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3325 if (!rule) {
3326 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003327 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003328 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003329 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3330 err_code |= warnif_cond_conflicts(rule->cond,
3331 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3332 file, linenum);
3333 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003334
3335 if (!already_warned(WARN_BLOCK_DEPRECATED))
3336 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]);
3337
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003338 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003339 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003340 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003341
Cyril Bonté99ed3272010-01-24 23:29:44 +01003342 if (curproxy == &defproxy) {
3343 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3344 err_code |= ERR_ALERT | ERR_FATAL;
3345 goto out;
3346 }
3347
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003348 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003349 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3350 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003351 err_code |= ERR_ALERT | ERR_FATAL;
3352 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003353 }
3354
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003355 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003356 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003357 err_code |= warnif_cond_conflicts(rule->cond,
3358 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3359 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003360 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003361 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003362 struct switching_rule *rule;
3363
Willy Tarreaub099aca2008-10-12 17:26:37 +02003364 if (curproxy == &defproxy) {
3365 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003366 err_code |= ERR_ALERT | ERR_FATAL;
3367 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003368 }
3369
Willy Tarreau55ea7572007-06-17 19:56:27 +02003370 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003371 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003372
3373 if (*(args[1]) == 0) {
3374 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003375 err_code |= ERR_ALERT | ERR_FATAL;
3376 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003377 }
3378
Willy Tarreauf51658d2014-04-23 01:21:56 +02003379 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3380 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3381 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3382 file, linenum, errmsg);
3383 err_code |= ERR_ALERT | ERR_FATAL;
3384 goto out;
3385 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003386
Willy Tarreauf51658d2014-04-23 01:21:56 +02003387 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003388 }
3389
3390 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3391 rule->cond = cond;
3392 rule->be.name = strdup(args[1]);
3393 LIST_INIT(&rule->list);
3394 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3395 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003396 else if (strcmp(args[0], "use-server") == 0) {
3397 struct server_rule *rule;
3398
3399 if (curproxy == &defproxy) {
3400 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3401 err_code |= ERR_ALERT | ERR_FATAL;
3402 goto out;
3403 }
3404
3405 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3406 err_code |= ERR_WARN;
3407
3408 if (*(args[1]) == 0) {
3409 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3410 err_code |= ERR_ALERT | ERR_FATAL;
3411 goto out;
3412 }
3413
3414 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3415 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3416 file, linenum, args[0]);
3417 err_code |= ERR_ALERT | ERR_FATAL;
3418 goto out;
3419 }
3420
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003421 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3422 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3423 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003424 err_code |= ERR_ALERT | ERR_FATAL;
3425 goto out;
3426 }
3427
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003428 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003429
3430 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3431 rule->cond = cond;
3432 rule->srv.name = strdup(args[1]);
3433 LIST_INIT(&rule->list);
3434 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3435 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3436 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003437 else if ((!strcmp(args[0], "force-persist")) ||
3438 (!strcmp(args[0], "ignore-persist"))) {
3439 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003440
3441 if (curproxy == &defproxy) {
3442 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3443 err_code |= ERR_ALERT | ERR_FATAL;
3444 goto out;
3445 }
3446
3447 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3448 err_code |= ERR_WARN;
3449
Willy Tarreauef6494c2010-01-28 17:12:36 +01003450 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003451 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3452 file, linenum, args[0]);
3453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
3455 }
3456
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003457 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3458 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3459 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003460 err_code |= ERR_ALERT | ERR_FATAL;
3461 goto out;
3462 }
3463
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003464 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3465 * where force-persist is applied.
3466 */
3467 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003468
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003469 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003470 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003471 if (!strcmp(args[0], "force-persist")) {
3472 rule->type = PERSIST_TYPE_FORCE;
3473 } else {
3474 rule->type = PERSIST_TYPE_IGNORE;
3475 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003476 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003477 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003478 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003479 else if (!strcmp(args[0], "stick-table")) {
3480 int myidx = 1;
3481
Emeric Brun32da3c42010-09-23 18:39:19 +02003482 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003483 curproxy->table.type = (unsigned int)-1;
3484 while (*args[myidx]) {
3485 const char *err;
3486
3487 if (strcmp(args[myidx], "size") == 0) {
3488 myidx++;
3489 if (!*(args[myidx])) {
3490 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3491 file, linenum, args[myidx-1]);
3492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
3494 }
3495 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3496 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3497 file, linenum, *err, args[myidx-1]);
3498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
3500 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003501 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003502 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003503 else if (strcmp(args[myidx], "peers") == 0) {
3504 myidx++;
Godbach50523162013-12-11 19:48:57 +08003505 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003506 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;
Godbach50523162013-12-11 19:48:57 +08003510 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003511 curproxy->table.peers.name = strdup(args[myidx++]);
3512 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003513 else if (strcmp(args[myidx], "expire") == 0) {
3514 myidx++;
3515 if (!*(args[myidx])) {
3516 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3517 file, linenum, args[myidx-1]);
3518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
3520 }
3521 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3522 if (err) {
3523 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3524 file, linenum, *err, args[myidx-1]);
3525 err_code |= ERR_ALERT | ERR_FATAL;
3526 goto out;
3527 }
3528 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003529 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003530 }
3531 else if (strcmp(args[myidx], "nopurge") == 0) {
3532 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003533 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003534 }
3535 else if (strcmp(args[myidx], "type") == 0) {
3536 myidx++;
3537 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3538 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3539 file, linenum, args[myidx]);
3540 err_code |= ERR_ALERT | ERR_FATAL;
3541 goto out;
3542 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003543 /* myidx already points to next arg */
3544 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003545 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003546 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003547 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003548
3549 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003550 nw = args[myidx];
3551 while (*nw) {
3552 /* the "store" keyword supports a comma-separated list */
3553 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003554 sa = NULL; /* store arg */
3555 while (*nw && *nw != ',') {
3556 if (*nw == '(') {
3557 *nw = 0;
3558 sa = ++nw;
3559 while (*nw != ')') {
3560 if (!*nw) {
3561 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3562 file, linenum, args[0], cw);
3563 err_code |= ERR_ALERT | ERR_FATAL;
3564 goto out;
3565 }
3566 nw++;
3567 }
3568 *nw = '\0';
3569 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003570 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003571 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003572 if (*nw)
3573 *nw++ = '\0';
3574 type = stktable_get_data_type(cw);
3575 if (type < 0) {
3576 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3577 file, linenum, args[0], cw);
3578 err_code |= ERR_ALERT | ERR_FATAL;
3579 goto out;
3580 }
Willy Tarreauac782882010-06-20 10:41:54 +02003581
3582 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3583 switch (err) {
3584 case PE_NONE: break;
3585 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003586 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3587 file, linenum, args[0], cw);
3588 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003589 break;
3590
3591 case PE_ARG_MISSING:
3592 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3593 file, linenum, args[0], cw);
3594 err_code |= ERR_ALERT | ERR_FATAL;
3595 goto out;
3596
3597 case PE_ARG_NOT_USED:
3598 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3599 file, linenum, args[0], cw);
3600 err_code |= ERR_ALERT | ERR_FATAL;
3601 goto out;
3602
3603 default:
3604 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3605 file, linenum, args[0], cw);
3606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003608 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003609 }
3610 myidx++;
3611 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003612 else {
3613 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3614 file, linenum, args[myidx]);
3615 err_code |= ERR_ALERT | ERR_FATAL;
3616 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003617 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003618 }
3619
3620 if (!curproxy->table.size) {
3621 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3622 file, linenum);
3623 err_code |= ERR_ALERT | ERR_FATAL;
3624 goto out;
3625 }
3626
3627 if (curproxy->table.type == (unsigned int)-1) {
3628 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3629 file, linenum);
3630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
3632 }
3633 }
3634 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003635 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003636 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003637 int myidx = 0;
3638 const char *name = NULL;
3639 int flags;
3640
3641 if (curproxy == &defproxy) {
3642 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3643 err_code |= ERR_ALERT | ERR_FATAL;
3644 goto out;
3645 }
3646
3647 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3648 err_code |= ERR_WARN;
3649 goto out;
3650 }
3651
3652 myidx++;
3653 if ((strcmp(args[myidx], "store") == 0) ||
3654 (strcmp(args[myidx], "store-request") == 0)) {
3655 myidx++;
3656 flags = STK_IS_STORE;
3657 }
3658 else if (strcmp(args[myidx], "store-response") == 0) {
3659 myidx++;
3660 flags = STK_IS_STORE | STK_ON_RSP;
3661 }
3662 else if (strcmp(args[myidx], "match") == 0) {
3663 myidx++;
3664 flags = STK_IS_MATCH;
3665 }
3666 else if (strcmp(args[myidx], "on") == 0) {
3667 myidx++;
3668 flags = STK_IS_MATCH | STK_IS_STORE;
3669 }
3670 else {
3671 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3672 err_code |= ERR_ALERT | ERR_FATAL;
3673 goto out;
3674 }
3675
3676 if (*(args[myidx]) == 0) {
3677 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3678 err_code |= ERR_ALERT | ERR_FATAL;
3679 goto out;
3680 }
3681
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003682 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003683 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003684 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003685 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003686 err_code |= ERR_ALERT | ERR_FATAL;
3687 goto out;
3688 }
3689
3690 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003691 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3692 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3693 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003694 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003695 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003696 goto out;
3697 }
3698 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003699 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3700 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3701 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003702 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003703 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003704 goto out;
3705 }
3706 }
3707
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003708 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003709 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003710
Emeric Brunb982a3d2010-01-04 15:45:53 +01003711 if (strcmp(args[myidx], "table") == 0) {
3712 myidx++;
3713 name = args[myidx++];
3714 }
3715
Willy Tarreauef6494c2010-01-28 17:12:36 +01003716 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003717 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3718 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3719 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003720 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003721 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003722 goto out;
3723 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003724 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003725 else if (*(args[myidx])) {
3726 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3727 file, linenum, args[0], args[myidx]);
3728 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003729 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003730 goto out;
3731 }
Emeric Brun97679e72010-09-23 17:56:44 +02003732 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003733 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003734 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003735 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003736
Emeric Brunb982a3d2010-01-04 15:45:53 +01003737 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3738 rule->cond = cond;
3739 rule->expr = expr;
3740 rule->flags = flags;
3741 rule->table.name = name ? strdup(name) : NULL;
3742 LIST_INIT(&rule->list);
3743 if (flags & STK_ON_RSP)
3744 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3745 else
3746 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003748 else if (!strcmp(args[0], "stats")) {
3749 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3750 curproxy->uri_auth = NULL; /* we must detach from the default config */
3751
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003752 if (!*args[1]) {
3753 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003754 } else if (!strcmp(args[1], "admin")) {
3755 struct stats_admin_rule *rule;
3756
3757 if (curproxy == &defproxy) {
3758 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3759 err_code |= ERR_ALERT | ERR_FATAL;
3760 goto out;
3761 }
3762
3763 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3764 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3765 err_code |= ERR_ALERT | ERR_ABORT;
3766 goto out;
3767 }
3768
3769 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3770 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3771 file, linenum, args[0], args[1]);
3772 err_code |= ERR_ALERT | ERR_FATAL;
3773 goto out;
3774 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003775 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3776 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3777 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003778 err_code |= ERR_ALERT | ERR_FATAL;
3779 goto out;
3780 }
3781
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003782 err_code |= warnif_cond_conflicts(cond,
3783 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3784 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003785
3786 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3787 rule->cond = cond;
3788 LIST_INIT(&rule->list);
3789 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003790 } else if (!strcmp(args[1], "uri")) {
3791 if (*(args[2]) == 0) {
3792 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\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_uri(&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 }
3800 } else if (!strcmp(args[1], "realm")) {
3801 if (*(args[2]) == 0) {
3802 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3806 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_ALERT | ERR_ABORT;
3808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003810 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003811 unsigned interval;
3812
3813 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3814 if (err) {
3815 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3816 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003817 err_code |= ERR_ALERT | ERR_FATAL;
3818 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003819 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3820 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003821 err_code |= ERR_ALERT | ERR_ABORT;
3822 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003823 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003824 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003825 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003826
3827 if (curproxy == &defproxy) {
3828 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3829 err_code |= ERR_ALERT | ERR_FATAL;
3830 goto out;
3831 }
3832
3833 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3834 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3835 err_code |= ERR_ALERT | ERR_ABORT;
3836 goto out;
3837 }
3838
Willy Tarreauff011f22011-01-06 17:51:27 +01003839 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3840 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003841 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3842 file, linenum, args[0]);
3843 err_code |= ERR_WARN;
3844 }
3845
Willy Tarreauff011f22011-01-06 17:51:27 +01003846 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003847
Willy Tarreauff011f22011-01-06 17:51:27 +01003848 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003849 err_code |= ERR_ALERT | ERR_ABORT;
3850 goto out;
3851 }
3852
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003853 err_code |= warnif_cond_conflicts(rule->cond,
3854 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3855 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003856 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003857
Willy Tarreaubaaee002006-06-26 02:48:02 +02003858 } else if (!strcmp(args[1], "auth")) {
3859 if (*(args[2]) == 0) {
3860 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\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_auth(&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], "scope")) {
3869 if (*(args[2]) == 0) {
3870 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_ALERT | ERR_FATAL;
3872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3874 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003875 err_code |= ERR_ALERT | ERR_ABORT;
3876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003877 }
3878 } else if (!strcmp(args[1], "enable")) {
3879 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3880 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003881 err_code |= ERR_ALERT | ERR_ABORT;
3882 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003883 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003884 } else if (!strcmp(args[1], "hide-version")) {
3885 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3886 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003887 err_code |= ERR_ALERT | ERR_ABORT;
3888 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003889 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003890 } else if (!strcmp(args[1], "show-legends")) {
3891 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3892 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3893 err_code |= ERR_ALERT | ERR_ABORT;
3894 goto out;
3895 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003896 } else if (!strcmp(args[1], "show-node")) {
3897
3898 if (*args[2]) {
3899 int i;
3900 char c;
3901
3902 for (i=0; args[2][i]; i++) {
3903 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003904 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3905 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003906 break;
3907 }
3908
3909 if (!i || args[2][i]) {
3910 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3911 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3912 file, linenum, args[0], args[1]);
3913 err_code |= ERR_ALERT | ERR_FATAL;
3914 goto out;
3915 }
3916 }
3917
3918 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3919 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3920 err_code |= ERR_ALERT | ERR_ABORT;
3921 goto out;
3922 }
3923 } else if (!strcmp(args[1], "show-desc")) {
3924 char *desc = NULL;
3925
3926 if (*args[2]) {
3927 int i, len=0;
3928 char *d;
3929
Willy Tarreau348acfe2014-04-14 15:00:39 +02003930 for (i = 2; *args[i]; i++)
3931 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003932
3933 desc = d = (char *)calloc(1, len);
3934
Willy Tarreau348acfe2014-04-14 15:00:39 +02003935 d += snprintf(d, desc + len - d, "%s", args[2]);
3936 for (i = 3; *args[i]; i++)
3937 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003938 }
3939
3940 if (!*args[2] && !global.desc)
3941 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3942 file, linenum, args[1]);
3943 else {
3944 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3945 free(desc);
3946 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3947 err_code |= ERR_ALERT | ERR_ABORT;
3948 goto out;
3949 }
3950 free(desc);
3951 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003952 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003953stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003954 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 +01003955 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1: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 }
3959 }
3960 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003961 int optnum;
3962
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003963 if (*(args[1]) == '\0') {
3964 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3965 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003968 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003969
3970 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3971 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003972 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3973 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3974 file, linenum, cfg_opts[optnum].name);
3975 err_code |= ERR_ALERT | ERR_FATAL;
3976 goto out;
3977 }
Willy Tarreau93893792009-07-23 13:19:11 +02003978 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3979 err_code |= ERR_WARN;
3980 goto out;
3981 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003982
Willy Tarreau3842f002009-06-14 11:39:52 +02003983 curproxy->no_options &= ~cfg_opts[optnum].val;
3984 curproxy->options &= ~cfg_opts[optnum].val;
3985
3986 switch (kwm) {
3987 case KWM_STD:
3988 curproxy->options |= cfg_opts[optnum].val;
3989 break;
3990 case KWM_NO:
3991 curproxy->no_options |= cfg_opts[optnum].val;
3992 break;
3993 case KWM_DEF: /* already cleared */
3994 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003995 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003996
Willy Tarreau93893792009-07-23 13:19:11 +02003997 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003998 }
3999 }
4000
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004001 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4002 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004003 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4004 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4005 file, linenum, cfg_opts2[optnum].name);
4006 err_code |= ERR_ALERT | ERR_FATAL;
4007 goto out;
4008 }
Willy Tarreau93893792009-07-23 13:19:11 +02004009 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4010 err_code |= ERR_WARN;
4011 goto out;
4012 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004013
Willy Tarreau3842f002009-06-14 11:39:52 +02004014 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4015 curproxy->options2 &= ~cfg_opts2[optnum].val;
4016
4017 switch (kwm) {
4018 case KWM_STD:
4019 curproxy->options2 |= cfg_opts2[optnum].val;
4020 break;
4021 case KWM_NO:
4022 curproxy->no_options2 |= cfg_opts2[optnum].val;
4023 break;
4024 case KWM_DEF: /* already cleared */
4025 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004026 }
Willy Tarreau93893792009-07-23 13:19:11 +02004027 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004028 }
4029 }
4030
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004031 /* HTTP options override each other. They can be cancelled using
4032 * "no option xxx" which only switches to default mode if the mode
4033 * was this one (useful for cancelling options set in defaults
4034 * sections).
4035 */
4036 if (strcmp(args[1], "httpclose") == 0) {
4037 if (kwm == KWM_STD) {
4038 curproxy->options &= ~PR_O_HTTP_MODE;
4039 curproxy->options |= PR_O_HTTP_PCL;
4040 goto out;
4041 }
4042 else if (kwm == KWM_NO) {
4043 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4044 curproxy->options &= ~PR_O_HTTP_MODE;
4045 goto out;
4046 }
4047 }
4048 else if (strcmp(args[1], "forceclose") == 0) {
4049 if (kwm == KWM_STD) {
4050 curproxy->options &= ~PR_O_HTTP_MODE;
4051 curproxy->options |= PR_O_HTTP_FCL;
4052 goto out;
4053 }
4054 else if (kwm == KWM_NO) {
4055 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4056 curproxy->options &= ~PR_O_HTTP_MODE;
4057 goto out;
4058 }
4059 }
4060 else if (strcmp(args[1], "http-server-close") == 0) {
4061 if (kwm == KWM_STD) {
4062 curproxy->options &= ~PR_O_HTTP_MODE;
4063 curproxy->options |= PR_O_HTTP_SCL;
4064 goto out;
4065 }
4066 else if (kwm == KWM_NO) {
4067 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4068 curproxy->options &= ~PR_O_HTTP_MODE;
4069 goto out;
4070 }
4071 }
4072 else if (strcmp(args[1], "http-keep-alive") == 0) {
4073 if (kwm == KWM_STD) {
4074 curproxy->options &= ~PR_O_HTTP_MODE;
4075 curproxy->options |= PR_O_HTTP_KAL;
4076 goto out;
4077 }
4078 else if (kwm == KWM_NO) {
4079 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4080 curproxy->options &= ~PR_O_HTTP_MODE;
4081 goto out;
4082 }
4083 }
4084 else if (strcmp(args[1], "http-tunnel") == 0) {
4085 if (kwm == KWM_STD) {
4086 curproxy->options &= ~PR_O_HTTP_MODE;
4087 curproxy->options |= PR_O_HTTP_TUN;
4088 goto out;
4089 }
4090 else if (kwm == KWM_NO) {
4091 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4092 curproxy->options &= ~PR_O_HTTP_MODE;
4093 goto out;
4094 }
4095 }
4096
Willy Tarreau3842f002009-06-14 11:39:52 +02004097 if (kwm != KWM_STD) {
4098 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004099 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004100 err_code |= ERR_ALERT | ERR_FATAL;
4101 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004102 }
4103
Emeric Brun3a058f32009-06-30 18:26:00 +02004104 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004105 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004106 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004107 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004108 if (*(args[2]) != '\0') {
4109 if (!strcmp(args[2], "clf")) {
4110 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004111 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004112 } else {
4113 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02004114 err_code |= ERR_ALERT | ERR_FATAL;
4115 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004116 }
4117 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004118 if (curproxy->conf.logformat_string != default_http_log_format &&
4119 curproxy->conf.logformat_string != default_tcp_log_format &&
4120 curproxy->conf.logformat_string != clf_http_log_format)
4121 free(curproxy->conf.logformat_string);
4122 curproxy->conf.logformat_string = logformat;
4123
4124 free(curproxy->conf.lfs_file);
4125 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4126 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004127 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004128 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004129 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004130 if (curproxy->conf.logformat_string != default_http_log_format &&
4131 curproxy->conf.logformat_string != default_tcp_log_format &&
4132 curproxy->conf.logformat_string != clf_http_log_format)
4133 free(curproxy->conf.logformat_string);
4134 curproxy->conf.logformat_string = default_tcp_log_format;
4135
4136 free(curproxy->conf.lfs_file);
4137 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4138 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004139 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004140 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004141 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004142 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004143 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004144
4145 if (curproxy->cap & PR_CAP_FE)
4146 curproxy->options |= PR_O_TCP_CLI_KA;
4147 if (curproxy->cap & PR_CAP_BE)
4148 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004149 }
4150 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004151 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004152 err_code |= ERR_WARN;
4153
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004155 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004156 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004157 curproxy->options2 &= ~PR_O2_CHK_ANY;
4158 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004159 if (!*args[2]) { /* no argument */
4160 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4161 curproxy->check_len = strlen(DEF_CHECK_REQ);
4162 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004163 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004164 curproxy->check_req = (char *)malloc(reqlen);
4165 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004166 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004167 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004168 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004169 if (*args[4])
4170 reqlen += strlen(args[4]);
4171 else
4172 reqlen += strlen("HTTP/1.0");
4173
4174 curproxy->check_req = (char *)malloc(reqlen);
4175 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004176 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004177 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004178 }
4179 else if (!strcmp(args[1], "ssl-hello-chk")) {
4180 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004181 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004182 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004183
Willy Tarreaua534fea2008-08-03 12:19:50 +02004184 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004185 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004186 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004187 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004188 }
Willy Tarreau23677902007-05-08 23:50:35 +02004189 else if (!strcmp(args[1], "smtpchk")) {
4190 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004191 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004192 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004193 curproxy->options2 &= ~PR_O2_CHK_ANY;
4194 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004195
4196 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4197 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4198 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4199 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4200 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4201 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4202 curproxy->check_req = (char *)malloc(reqlen);
4203 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4204 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4205 } else {
4206 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4207 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4208 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4209 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4210 }
4211 }
4212 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004213 else if (!strcmp(args[1], "pgsql-check")) {
4214 /* use PostgreSQL request to check servers' health */
4215 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4216 err_code |= ERR_WARN;
4217
4218 free(curproxy->check_req);
4219 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004220 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004221 curproxy->options2 |= PR_O2_PGSQL_CHK;
4222
4223 if (*(args[2])) {
4224 int cur_arg = 2;
4225
4226 while (*(args[cur_arg])) {
4227 if (strcmp(args[cur_arg], "user") == 0) {
4228 char * packet;
4229 uint32_t packet_len;
4230 uint32_t pv;
4231
4232 /* suboption header - needs additional argument for it */
4233 if (*(args[cur_arg+1]) == 0) {
4234 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4235 file, linenum, args[0], args[1], args[cur_arg]);
4236 err_code |= ERR_ALERT | ERR_FATAL;
4237 goto out;
4238 }
4239
4240 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4241 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4242 pv = htonl(0x30000); /* protocol version 3.0 */
4243
4244 packet = (char*) calloc(1, packet_len);
4245
4246 memcpy(packet + 4, &pv, 4);
4247
4248 /* copy "user" */
4249 memcpy(packet + 8, "user", 4);
4250
4251 /* copy username */
4252 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4253
4254 free(curproxy->check_req);
4255 curproxy->check_req = packet;
4256 curproxy->check_len = packet_len;
4257
4258 packet_len = htonl(packet_len);
4259 memcpy(packet, &packet_len, 4);
4260 cur_arg += 2;
4261 } else {
4262 /* unknown suboption - catchall */
4263 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4264 file, linenum, args[0], args[1]);
4265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
4267 }
4268 } /* end while loop */
4269 }
4270 }
4271
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004272 else if (!strcmp(args[1], "redis-check")) {
4273 /* use REDIS PING request to check servers' health */
4274 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4275 err_code |= ERR_WARN;
4276
4277 free(curproxy->check_req);
4278 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004279 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004280 curproxy->options2 |= PR_O2_REDIS_CHK;
4281
4282 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4283 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4284 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4285 }
4286
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004287 else if (!strcmp(args[1], "mysql-check")) {
4288 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004289 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4290 err_code |= ERR_WARN;
4291
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004292 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004293 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004294 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004295 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004296
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004297 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004298 * const char mysql40_client_auth_pkt[] = {
4299 * "\x0e\x00\x00" // packet length
4300 * "\x01" // packet number
4301 * "\x00\x00" // client capabilities
4302 * "\x00\x00\x01" // max packet
4303 * "haproxy\x00" // username (null terminated string)
4304 * "\x00" // filler (always 0x00)
4305 * "\x01\x00\x00" // packet length
4306 * "\x00" // packet number
4307 * "\x01" // COM_QUIT command
4308 * };
4309 */
4310
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004311 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4312 * const char mysql41_client_auth_pkt[] = {
4313 * "\x0e\x00\x00\" // packet length
4314 * "\x01" // packet number
4315 * "\x00\x00\x00\x00" // client capabilities
4316 * "\x00\x00\x00\x01" // max packet
4317 * "\x21" // character set (UTF-8)
4318 * char[23] // All zeroes
4319 * "haproxy\x00" // username (null terminated string)
4320 * "\x00" // filler (always 0x00)
4321 * "\x01\x00\x00" // packet length
4322 * "\x00" // packet number
4323 * "\x01" // COM_QUIT command
4324 * };
4325 */
4326
4327
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004328 if (*(args[2])) {
4329 int cur_arg = 2;
4330
4331 while (*(args[cur_arg])) {
4332 if (strcmp(args[cur_arg], "user") == 0) {
4333 char *mysqluser;
4334 int packetlen, reqlen, userlen;
4335
4336 /* suboption header - needs additional argument for it */
4337 if (*(args[cur_arg+1]) == 0) {
4338 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4339 file, linenum, args[0], args[1], args[cur_arg]);
4340 err_code |= ERR_ALERT | ERR_FATAL;
4341 goto out;
4342 }
4343 mysqluser = args[cur_arg + 1];
4344 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004345
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004346 if (*(args[cur_arg+2])) {
4347 if (!strcmp(args[cur_arg+2], "post-41")) {
4348 packetlen = userlen + 7 + 27;
4349 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004350
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004351 free(curproxy->check_req);
4352 curproxy->check_req = (char *)calloc(1, reqlen);
4353 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004354
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004355 snprintf(curproxy->check_req, 4, "%c%c%c",
4356 ((unsigned char) packetlen & 0xff),
4357 ((unsigned char) (packetlen >> 8) & 0xff),
4358 ((unsigned char) (packetlen >> 16) & 0xff));
4359
4360 curproxy->check_req[3] = 1;
4361 curproxy->check_req[5] = 130;
4362 curproxy->check_req[11] = 1;
4363 curproxy->check_req[12] = 33;
4364 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4365 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4366 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4367 cur_arg += 3;
4368 } else {
4369 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4370 err_code |= ERR_ALERT | ERR_FATAL;
4371 goto out;
4372 }
4373 } else {
4374 packetlen = userlen + 7;
4375 reqlen = packetlen + 9;
4376
4377 free(curproxy->check_req);
4378 curproxy->check_req = (char *)calloc(1, reqlen);
4379 curproxy->check_len = reqlen;
4380
4381 snprintf(curproxy->check_req, 4, "%c%c%c",
4382 ((unsigned char) packetlen & 0xff),
4383 ((unsigned char) (packetlen >> 8) & 0xff),
4384 ((unsigned char) (packetlen >> 16) & 0xff));
4385
4386 curproxy->check_req[3] = 1;
4387 curproxy->check_req[5] = 128;
4388 curproxy->check_req[8] = 1;
4389 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4390 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4391 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4392 cur_arg += 2;
4393 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004394 } else {
4395 /* unknown suboption - catchall */
4396 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4397 file, linenum, args[0], args[1]);
4398 err_code |= ERR_ALERT | ERR_FATAL;
4399 goto out;
4400 }
4401 } /* end while loop */
4402 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004403 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004404 else if (!strcmp(args[1], "ldap-check")) {
4405 /* use LDAP request to check servers' health */
4406 free(curproxy->check_req);
4407 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004408 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004409 curproxy->options2 |= PR_O2_LDAP_CHK;
4410
4411 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4412 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4413 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4414 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004415 else if (!strcmp(args[1], "tcp-check")) {
4416 /* use raw TCPCHK send/expect to check servers' health */
4417 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4418 err_code |= ERR_WARN;
4419
4420 free(curproxy->check_req);
4421 curproxy->check_req = NULL;
4422 curproxy->options2 &= ~PR_O2_CHK_ANY;
4423 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4424 }
Simon Horman98637e52014-06-20 12:30:16 +09004425 else if (!strcmp(args[1], "external-check")) {
4426 /* excute an external command to check servers' health */
4427 free(curproxy->check_req);
4428 curproxy->check_req = NULL;
4429 curproxy->options2 &= ~PR_O2_CHK_ANY;
4430 curproxy->options2 |= PR_O2_EXT_CHK;
4431 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004432 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004433 int cur_arg;
4434
4435 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4436 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004437 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004438
Willy Tarreau87cf5142011-08-19 22:57:24 +02004439 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004440
4441 free(curproxy->fwdfor_hdr_name);
4442 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4443 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4444
4445 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4446 cur_arg = 2;
4447 while (*(args[cur_arg])) {
4448 if (!strcmp(args[cur_arg], "except")) {
4449 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004450 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004451 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4452 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004455 }
4456 /* flush useless bits */
4457 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004458 cur_arg += 2;
4459 } else if (!strcmp(args[cur_arg], "header")) {
4460 /* suboption header - needs additional argument for it */
4461 if (*(args[cur_arg+1]) == 0) {
4462 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4463 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004464 err_code |= ERR_ALERT | ERR_FATAL;
4465 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004466 }
4467 free(curproxy->fwdfor_hdr_name);
4468 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4469 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4470 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004471 } else if (!strcmp(args[cur_arg], "if-none")) {
4472 curproxy->options &= ~PR_O_FF_ALWAYS;
4473 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004474 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004475 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004476 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004477 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004478 err_code |= ERR_ALERT | ERR_FATAL;
4479 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004480 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004481 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004482 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004483 else if (!strcmp(args[1], "originalto")) {
4484 int cur_arg;
4485
4486 /* insert x-original-to field, but not for the IP address listed as an except.
4487 * set default options (ie: bitfield, header name, etc)
4488 */
4489
4490 curproxy->options |= PR_O_ORGTO;
4491
4492 free(curproxy->orgto_hdr_name);
4493 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4494 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4495
Willy Tarreau87cf5142011-08-19 22:57:24 +02004496 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004497 cur_arg = 2;
4498 while (*(args[cur_arg])) {
4499 if (!strcmp(args[cur_arg], "except")) {
4500 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004501 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 +02004502 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4503 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004504 err_code |= ERR_ALERT | ERR_FATAL;
4505 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004506 }
4507 /* flush useless bits */
4508 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4509 cur_arg += 2;
4510 } else if (!strcmp(args[cur_arg], "header")) {
4511 /* suboption header - needs additional argument for it */
4512 if (*(args[cur_arg+1]) == 0) {
4513 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4514 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004515 err_code |= ERR_ALERT | ERR_FATAL;
4516 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004517 }
4518 free(curproxy->orgto_hdr_name);
4519 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4520 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4521 cur_arg += 2;
4522 } else {
4523 /* unknown suboption - catchall */
4524 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4525 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004526 err_code |= ERR_ALERT | ERR_FATAL;
4527 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004528 }
4529 } /* end while loop */
4530 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004531 else {
4532 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004533 err_code |= ERR_ALERT | ERR_FATAL;
4534 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004535 }
Willy Tarreau93893792009-07-23 13:19:11 +02004536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004537 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004538 else if (!strcmp(args[0], "default_backend")) {
4539 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004540 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004541
4542 if (*(args[1]) == 0) {
4543 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004544 err_code |= ERR_ALERT | ERR_FATAL;
4545 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004546 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004547 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004548 curproxy->defbe.name = strdup(args[1]);
4549 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004550 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004551 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004552 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004553
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004554 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4555 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 +01004556 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004557 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004558 /* enable reconnections to dispatch */
4559 curproxy->options |= PR_O_REDISP;
4560 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004561 else if (!strcmp(args[0], "http-check")) {
4562 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004563 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004564
4565 if (strcmp(args[1], "disable-on-404") == 0) {
4566 /* enable a graceful server shutdown on an HTTP 404 response */
4567 curproxy->options |= PR_O_DISABLE404;
4568 }
Willy Tarreauef781042010-01-27 11:53:01 +01004569 else if (strcmp(args[1], "send-state") == 0) {
4570 /* enable emission of the apparent state of a server in HTTP checks */
4571 curproxy->options2 |= PR_O2_CHK_SNDST;
4572 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004573 else if (strcmp(args[1], "expect") == 0) {
4574 const char *ptr_arg;
4575 int cur_arg;
4576
4577 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4578 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4579 err_code |= ERR_ALERT | ERR_FATAL;
4580 goto out;
4581 }
4582
4583 cur_arg = 2;
4584 /* consider exclamation marks, sole or at the beginning of a word */
4585 while (*(ptr_arg = args[cur_arg])) {
4586 while (*ptr_arg == '!') {
4587 curproxy->options2 ^= PR_O2_EXP_INV;
4588 ptr_arg++;
4589 }
4590 if (*ptr_arg)
4591 break;
4592 cur_arg++;
4593 }
4594 /* now ptr_arg points to the beginning of a word past any possible
4595 * exclamation mark, and cur_arg is the argument which holds this word.
4596 */
4597 if (strcmp(ptr_arg, "status") == 0) {
4598 if (!*(args[cur_arg + 1])) {
4599 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4600 file, linenum, args[0], args[1], ptr_arg);
4601 err_code |= ERR_ALERT | ERR_FATAL;
4602 goto out;
4603 }
4604 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004605 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004606 curproxy->expect_str = strdup(args[cur_arg + 1]);
4607 }
4608 else if (strcmp(ptr_arg, "string") == 0) {
4609 if (!*(args[cur_arg + 1])) {
4610 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4611 file, linenum, args[0], args[1], ptr_arg);
4612 err_code |= ERR_ALERT | ERR_FATAL;
4613 goto out;
4614 }
4615 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004616 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004617 curproxy->expect_str = strdup(args[cur_arg + 1]);
4618 }
4619 else if (strcmp(ptr_arg, "rstatus") == 0) {
4620 if (!*(args[cur_arg + 1])) {
4621 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4622 file, linenum, args[0], args[1], ptr_arg);
4623 err_code |= ERR_ALERT | ERR_FATAL;
4624 goto out;
4625 }
4626 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004627 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004628 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004629 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004630 free(curproxy->expect_regex);
4631 curproxy->expect_regex = NULL;
4632 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004633 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004634 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4635 error = NULL;
4636 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4637 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4638 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4639 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004640 err_code |= ERR_ALERT | ERR_FATAL;
4641 goto out;
4642 }
4643 }
4644 else if (strcmp(ptr_arg, "rstring") == 0) {
4645 if (!*(args[cur_arg + 1])) {
4646 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4647 file, linenum, args[0], args[1], ptr_arg);
4648 err_code |= ERR_ALERT | ERR_FATAL;
4649 goto out;
4650 }
4651 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004652 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004653 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004654 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004655 free(curproxy->expect_regex);
4656 curproxy->expect_regex = NULL;
4657 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004658 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004659 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4660 error = NULL;
4661 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4662 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4663 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4664 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004665 err_code |= ERR_ALERT | ERR_FATAL;
4666 goto out;
4667 }
4668 }
4669 else {
4670 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4671 file, linenum, args[0], args[1], ptr_arg);
4672 err_code |= ERR_ALERT | ERR_FATAL;
4673 goto out;
4674 }
4675 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004676 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004677 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 +02004678 err_code |= ERR_ALERT | ERR_FATAL;
4679 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004680 }
4681 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004682 else if (!strcmp(args[0], "tcp-check")) {
4683 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4684 err_code |= ERR_WARN;
4685
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004686 if (strcmp(args[1], "comment") == 0) {
4687 int cur_arg;
4688 struct tcpcheck_rule *tcpcheck;
4689
4690 cur_arg = 1;
4691 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4692 tcpcheck->action = TCPCHK_ACT_COMMENT;
4693
4694 if (!*args[cur_arg + 1]) {
4695 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4696 file, linenum, args[cur_arg]);
4697 err_code |= ERR_ALERT | ERR_FATAL;
4698 goto out;
4699 }
4700
4701 tcpcheck->comment = strdup(args[cur_arg + 1]);
4702
4703 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4704 }
4705 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004706 const char *ptr_arg;
4707 int cur_arg;
4708 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004709
4710 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02004711 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
4712 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
4713 tcpcheck->action == TCPCHK_ACT_COMMENT) {
4714 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
4715 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004716
Willy Tarreau5581c272015-05-13 12:24:53 +02004717 if (&tcpcheck->list != &curproxy->tcpcheck_rules
4718 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4719 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4720 file, linenum);
4721 err_code |= ERR_ALERT | ERR_FATAL;
4722 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004723 }
4724
4725 cur_arg = 2;
4726 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4727 tcpcheck->action = TCPCHK_ACT_CONNECT;
4728
4729 /* parsing each parameters to fill up the rule */
4730 while (*(ptr_arg = args[cur_arg])) {
4731 /* tcp port */
4732 if (strcmp(args[cur_arg], "port") == 0) {
4733 if ( (atol(args[cur_arg + 1]) > 65535) ||
4734 (atol(args[cur_arg + 1]) < 1) ){
4735 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4736 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4737 err_code |= ERR_ALERT | ERR_FATAL;
4738 goto out;
4739 }
4740 tcpcheck->port = atol(args[cur_arg + 1]);
4741 cur_arg += 2;
4742 }
4743 /* send proxy protocol */
4744 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4745 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4746 cur_arg++;
4747 }
4748#ifdef USE_OPENSSL
4749 else if (strcmp(args[cur_arg], "ssl") == 0) {
4750 curproxy->options |= PR_O_TCPCHK_SSL;
4751 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4752 cur_arg++;
4753 }
4754#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004755 /* comment for this tcpcheck line */
4756 else if (strcmp(args[cur_arg], "comment") == 0) {
4757 if (!*args[cur_arg + 1]) {
4758 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4759 file, linenum, args[cur_arg]);
4760 err_code |= ERR_ALERT | ERR_FATAL;
4761 goto out;
4762 }
4763 tcpcheck->comment = strdup(args[cur_arg + 1]);
4764 cur_arg += 2;
4765 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004766 else {
4767#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004768 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 +01004769#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004770 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 +01004771#endif /* USE_OPENSSL */
4772 file, linenum, args[0], args[1], args[cur_arg]);
4773 err_code |= ERR_ALERT | ERR_FATAL;
4774 goto out;
4775 }
4776
4777 }
4778
4779 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4780 }
4781 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004782 if (! *(args[2]) ) {
4783 /* SEND string expected */
4784 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4785 file, linenum, args[0], args[1], args[2]);
4786 err_code |= ERR_ALERT | ERR_FATAL;
4787 goto out;
4788 } else {
4789 struct tcpcheck_rule *tcpcheck;
4790
4791 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4792
4793 tcpcheck->action = TCPCHK_ACT_SEND;
4794 tcpcheck->string_len = strlen(args[2]);
4795 tcpcheck->string = strdup(args[2]);
4796 tcpcheck->expect_regex = NULL;
4797
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004798 /* comment for this tcpcheck line */
4799 if (strcmp(args[3], "comment") == 0) {
4800 if (!*args[4]) {
4801 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4802 file, linenum, args[3]);
4803 err_code |= ERR_ALERT | ERR_FATAL;
4804 goto out;
4805 }
4806 tcpcheck->comment = strdup(args[4]);
4807 }
4808
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004809 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4810 }
4811 }
4812 else if (strcmp(args[1], "send-binary") == 0) {
4813 if (! *(args[2]) ) {
4814 /* SEND binary string expected */
4815 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4816 file, linenum, args[0], args[1], args[2]);
4817 err_code |= ERR_ALERT | ERR_FATAL;
4818 goto out;
4819 } else {
4820 struct tcpcheck_rule *tcpcheck;
4821 char *err = NULL;
4822
4823 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4824
4825 tcpcheck->action = TCPCHK_ACT_SEND;
4826 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4827 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4828 file, linenum, args[0], args[1], args[2], err);
4829 err_code |= ERR_ALERT | ERR_FATAL;
4830 goto out;
4831 }
4832 tcpcheck->expect_regex = NULL;
4833
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004834 /* comment for this tcpcheck line */
4835 if (strcmp(args[3], "comment") == 0) {
4836 if (!*args[4]) {
4837 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4838 file, linenum, args[3]);
4839 err_code |= ERR_ALERT | ERR_FATAL;
4840 goto out;
4841 }
4842 tcpcheck->comment = strdup(args[4]);
4843 }
4844
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004845 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4846 }
4847 }
4848 else if (strcmp(args[1], "expect") == 0) {
4849 const char *ptr_arg;
4850 int cur_arg;
4851 int inverse = 0;
4852
4853 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4854 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4855 err_code |= ERR_ALERT | ERR_FATAL;
4856 goto out;
4857 }
4858
4859 cur_arg = 2;
4860 /* consider exclamation marks, sole or at the beginning of a word */
4861 while (*(ptr_arg = args[cur_arg])) {
4862 while (*ptr_arg == '!') {
4863 inverse = !inverse;
4864 ptr_arg++;
4865 }
4866 if (*ptr_arg)
4867 break;
4868 cur_arg++;
4869 }
4870 /* now ptr_arg points to the beginning of a word past any possible
4871 * exclamation mark, and cur_arg is the argument which holds this word.
4872 */
4873 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004874 struct tcpcheck_rule *tcpcheck;
4875 char *err = NULL;
4876
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004877 if (!*(args[cur_arg + 1])) {
4878 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4879 file, linenum, args[0], args[1], ptr_arg);
4880 err_code |= ERR_ALERT | ERR_FATAL;
4881 goto out;
4882 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004883
4884 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4885
4886 tcpcheck->action = TCPCHK_ACT_EXPECT;
4887 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4888 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4889 file, linenum, args[0], args[1], args[2], err);
4890 err_code |= ERR_ALERT | ERR_FATAL;
4891 goto out;
4892 }
4893 tcpcheck->expect_regex = NULL;
4894 tcpcheck->inverse = inverse;
4895
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004896 /* tcpcheck comment */
4897 cur_arg += 2;
4898 if (strcmp(args[cur_arg], "comment") == 0) {
4899 if (!*args[cur_arg + 1]) {
4900 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4901 file, linenum, args[cur_arg + 1]);
4902 err_code |= ERR_ALERT | ERR_FATAL;
4903 goto out;
4904 }
4905 tcpcheck->comment = strdup(args[cur_arg + 1]);
4906 }
4907
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004908 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4909 }
4910 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004911 struct tcpcheck_rule *tcpcheck;
4912
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004913 if (!*(args[cur_arg + 1])) {
4914 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4915 file, linenum, args[0], args[1], ptr_arg);
4916 err_code |= ERR_ALERT | ERR_FATAL;
4917 goto out;
4918 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004919
4920 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4921
4922 tcpcheck->action = TCPCHK_ACT_EXPECT;
4923 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4924 tcpcheck->string = strdup(args[cur_arg + 1]);
4925 tcpcheck->expect_regex = NULL;
4926 tcpcheck->inverse = inverse;
4927
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004928 /* tcpcheck comment */
4929 cur_arg += 2;
4930 if (strcmp(args[cur_arg], "comment") == 0) {
4931 if (!*args[cur_arg + 1]) {
4932 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4933 file, linenum, args[cur_arg + 1]);
4934 err_code |= ERR_ALERT | ERR_FATAL;
4935 goto out;
4936 }
4937 tcpcheck->comment = strdup(args[cur_arg + 1]);
4938 }
4939
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004940 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4941 }
4942 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004943 struct tcpcheck_rule *tcpcheck;
4944
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004945 if (!*(args[cur_arg + 1])) {
4946 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4947 file, linenum, args[0], args[1], ptr_arg);
4948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
4950 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004951
4952 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4953
4954 tcpcheck->action = TCPCHK_ACT_EXPECT;
4955 tcpcheck->string_len = 0;
4956 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004957 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4958 error = NULL;
4959 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4960 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4961 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4962 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004963 err_code |= ERR_ALERT | ERR_FATAL;
4964 goto out;
4965 }
4966 tcpcheck->inverse = inverse;
4967
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004968 /* tcpcheck comment */
4969 cur_arg += 2;
4970 if (strcmp(args[cur_arg], "comment") == 0) {
4971 if (!*args[cur_arg + 1]) {
4972 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
4973 file, linenum, args[cur_arg + 1]);
4974 err_code |= ERR_ALERT | ERR_FATAL;
4975 goto out;
4976 }
4977 tcpcheck->comment = strdup(args[cur_arg + 1]);
4978 }
4979
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004980 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4981 }
4982 else {
4983 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4984 file, linenum, args[0], args[1], ptr_arg);
4985 err_code |= ERR_ALERT | ERR_FATAL;
4986 goto out;
4987 }
4988 }
4989 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02004990 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004991 err_code |= ERR_ALERT | ERR_FATAL;
4992 goto out;
4993 }
4994 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004995 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004996 if (curproxy == &defproxy) {
4997 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004998 err_code |= ERR_ALERT | ERR_FATAL;
4999 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005000 }
5001
Willy Tarreaub80c2302007-11-30 20:51:32 +01005002 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005003 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005004
5005 if (strcmp(args[1], "fail") == 0) {
5006 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005007 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005008 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5009 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005010 err_code |= ERR_ALERT | ERR_FATAL;
5011 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005012 }
5013
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005014 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5015 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5016 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005017 err_code |= ERR_ALERT | ERR_FATAL;
5018 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005019 }
5020 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5021 }
5022 else {
5023 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005024 err_code |= ERR_ALERT | ERR_FATAL;
5025 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005026 }
5027 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005028#ifdef TPROXY
5029 else if (!strcmp(args[0], "transparent")) {
5030 /* enable transparent proxy connections */
5031 curproxy->options |= PR_O_TRANSP;
5032 }
5033#endif
5034 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005035 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005036 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005037
Willy Tarreaubaaee002006-06-26 02:48:02 +02005038 if (*(args[1]) == 0) {
5039 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005040 err_code |= ERR_ALERT | ERR_FATAL;
5041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005042 }
5043 curproxy->maxconn = atol(args[1]);
5044 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005045 else if (!strcmp(args[0], "backlog")) { /* backlog */
5046 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005047 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005048
5049 if (*(args[1]) == 0) {
5050 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005051 err_code |= ERR_ALERT | ERR_FATAL;
5052 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005053 }
5054 curproxy->backlog = atol(args[1]);
5055 }
Willy Tarreau86034312006-12-29 00:10:33 +01005056 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005057 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005058 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005059
Willy Tarreau86034312006-12-29 00:10:33 +01005060 if (*(args[1]) == 0) {
5061 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005062 err_code |= ERR_ALERT | ERR_FATAL;
5063 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005064 }
5065 curproxy->fullconn = atol(args[1]);
5066 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005067 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5068 if (*(args[1]) == 0) {
5069 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005070 err_code |= ERR_ALERT | ERR_FATAL;
5071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005072 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005073 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5074 if (err) {
5075 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5076 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005077 err_code |= ERR_ALERT | ERR_FATAL;
5078 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005079 }
5080 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005081 }
5082 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005083 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005084 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005085 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005086
Willy Tarreaubaaee002006-06-26 02:48:02 +02005087 if (curproxy == &defproxy) {
5088 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005089 err_code |= ERR_ALERT | ERR_FATAL;
5090 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005091 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005092 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005093 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005094
Willy Tarreau902636f2013-03-10 19:44:48 +01005095 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005096 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005097 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005098 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005099 goto out;
5100 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005101
5102 proto = protocol_by_family(sk->ss_family);
5103 if (!proto || !proto->connect) {
5104 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5105 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005106 err_code |= ERR_ALERT | ERR_FATAL;
5107 goto out;
5108 }
5109
5110 if (port1 != port2) {
5111 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5112 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005113 err_code |= ERR_ALERT | ERR_FATAL;
5114 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005115 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005116
5117 if (!port1) {
5118 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5119 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005120 err_code |= ERR_ALERT | ERR_FATAL;
5121 goto out;
5122 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005123
Willy Tarreaud5191e72010-02-09 20:50:45 +01005124 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005125 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005126 }
5127 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005128 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005129 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005130
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005131 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5132 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005133 err_code |= ERR_ALERT | ERR_FATAL;
5134 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005135 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005136 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005137 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005138 /**
5139 * The syntax for hash-type config element is
5140 * hash-type {map-based|consistent} [[<algo>] avalanche]
5141 *
5142 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5143 */
5144 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005145
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005146 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5147 err_code |= ERR_WARN;
5148
5149 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005150 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5151 }
5152 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005153 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5154 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005155 else if (strcmp(args[1], "avalanche") == 0) {
5156 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]);
5157 err_code |= ERR_ALERT | ERR_FATAL;
5158 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005159 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005160 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005161 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005162 err_code |= ERR_ALERT | ERR_FATAL;
5163 goto out;
5164 }
Bhaskar98634f02013-10-29 23:30:51 -04005165
5166 /* set the hash function to use */
5167 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005168 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005169 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005170
5171 /* if consistent with no argument, then avalanche modifier is also applied */
5172 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5173 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005174 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005175 /* set the hash function */
5176 if (!strcmp(args[2], "sdbm")) {
5177 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5178 }
5179 else if (!strcmp(args[2], "djb2")) {
5180 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005181 }
5182 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005183 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005184 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005185 else if (!strcmp(args[2], "crc32")) {
5186 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5187 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005188 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005189 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 -05005190 err_code |= ERR_ALERT | ERR_FATAL;
5191 goto out;
5192 }
5193
5194 /* set the hash modifier */
5195 if (!strcmp(args[3], "avalanche")) {
5196 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5197 }
5198 else if (*args[3]) {
5199 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5200 err_code |= ERR_ALERT | ERR_FATAL;
5201 goto out;
5202 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005203 }
William Lallemanda73203e2012-03-12 12:48:57 +01005204 }
William Lallemanda73203e2012-03-12 12:48:57 +01005205 else if (strcmp(args[0], "unique-id-format") == 0) {
5206 if (!*(args[1])) {
5207 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5208 err_code |= ERR_ALERT | ERR_FATAL;
5209 goto out;
5210 }
William Lallemand3203ff42012-11-11 17:30:56 +01005211 if (*(args[2])) {
5212 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5213 err_code |= ERR_ALERT | ERR_FATAL;
5214 goto out;
5215 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005216 free(curproxy->conf.uniqueid_format_string);
5217 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005218
Willy Tarreau62a61232013-04-12 18:13:46 +02005219 free(curproxy->conf.uif_file);
5220 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5221 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005222 }
William Lallemanda73203e2012-03-12 12:48:57 +01005223
5224 else if (strcmp(args[0], "unique-id-header") == 0) {
5225 if (!*(args[1])) {
5226 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
5229 }
5230 free(curproxy->header_unique_id);
5231 curproxy->header_unique_id = strdup(args[1]);
5232 }
5233
William Lallemand723b73a2012-02-08 16:37:49 +01005234 else if (strcmp(args[0], "log-format") == 0) {
5235 if (!*(args[1])) {
5236 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5237 err_code |= ERR_ALERT | ERR_FATAL;
5238 goto out;
5239 }
William Lallemand3203ff42012-11-11 17:30:56 +01005240 if (*(args[2])) {
5241 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5242 err_code |= ERR_ALERT | ERR_FATAL;
5243 goto out;
5244 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005245
Willy Tarreau62a61232013-04-12 18:13:46 +02005246 if (curproxy->conf.logformat_string != default_http_log_format &&
5247 curproxy->conf.logformat_string != default_tcp_log_format &&
5248 curproxy->conf.logformat_string != clf_http_log_format)
5249 free(curproxy->conf.logformat_string);
5250 curproxy->conf.logformat_string = strdup(args[1]);
5251
5252 free(curproxy->conf.lfs_file);
5253 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5254 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005255
5256 /* get a chance to improve log-format error reporting by
5257 * reporting the correct line-number when possible.
5258 */
5259 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5260 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5261 file, linenum, curproxy->id);
5262 err_code |= ERR_WARN;
5263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005264 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005265 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5266 if (*(args[1]) == 0) {
5267 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5268 err_code |= ERR_ALERT | ERR_FATAL;
5269 goto out;
5270 }
5271 free(curproxy->log_tag);
5272 curproxy->log_tag = strdup(args[1]);
5273 }
William Lallemand0f99e342011-10-12 17:50:54 +02005274 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5275 /* delete previous herited or defined syslog servers */
5276 struct logsrv *back;
5277
5278 if (*(args[1]) != 0) {
5279 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5280 err_code |= ERR_ALERT | ERR_FATAL;
5281 goto out;
5282 }
5283
William Lallemand723b73a2012-02-08 16:37:49 +01005284 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5285 LIST_DEL(&tmplogsrv->list);
5286 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005287 }
5288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005289 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005290 struct logsrv *logsrv;
5291
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005293 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005294 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005295 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005296 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005297 LIST_INIT(&node->list);
5298 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5299 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005300 }
5301 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005302 struct sockaddr_storage *sk;
5303 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005304 int arg = 0;
5305 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005306
5307 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308
Willy Tarreau18324f52014-06-27 18:10:07 +02005309 /* just after the address, a length may be specified */
5310 if (strcmp(args[arg+2], "len") == 0) {
5311 len = atoi(args[arg+3]);
5312 if (len < 80 || len > 65535) {
5313 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5314 file, linenum, args[arg+3]);
5315 err_code |= ERR_ALERT | ERR_FATAL;
5316 goto out;
5317 }
5318 logsrv->maxlen = len;
5319
5320 /* skip these two args */
5321 arg += 2;
5322 }
5323 else
5324 logsrv->maxlen = MAX_SYSLOG_LEN;
5325
5326 if (logsrv->maxlen > global.max_syslog_len) {
5327 global.max_syslog_len = logsrv->maxlen;
5328 logline = realloc(logline, global.max_syslog_len + 1);
5329 }
5330
5331 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005332 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005333 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005334 err_code |= ERR_ALERT | ERR_FATAL;
5335 goto out;
5336
Willy Tarreaubaaee002006-06-26 02:48:02 +02005337 }
5338
William Lallemand0f99e342011-10-12 17:50:54 +02005339 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005340 if (*(args[arg+3])) {
5341 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005342 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005343 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005344 err_code |= ERR_ALERT | ERR_FATAL;
5345 goto out;
5346
Willy Tarreaubaaee002006-06-26 02:48:02 +02005347 }
5348 }
5349
William Lallemand0f99e342011-10-12 17:50:54 +02005350 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005351 if (*(args[arg+4])) {
5352 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005353 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005354 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005355 err_code |= ERR_ALERT | ERR_FATAL;
5356 goto out;
5357
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005358 }
5359 }
5360
Willy Tarreau902636f2013-03-10 19:44:48 +01005361 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005362 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005363 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005364 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005365 goto out;
5366 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005367
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005368 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005369
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005370 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005371 if (port1 != port2) {
5372 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5373 file, linenum, args[0], args[1]);
5374 err_code |= ERR_ALERT | ERR_FATAL;
5375 goto out;
5376 }
5377
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005378 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005379 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005380 }
William Lallemand0f99e342011-10-12 17:50:54 +02005381
5382 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005383 }
5384 else {
5385 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5386 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005387 err_code |= ERR_ALERT | ERR_FATAL;
5388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005389 }
5390 }
5391 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005392 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005393 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005394 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005395 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005396
Willy Tarreau977b8e42006-12-29 14:19:17 +01005397 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005398 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005399
Willy Tarreaubaaee002006-06-26 02:48:02 +02005400 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005401 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5402 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005403 err_code |= ERR_ALERT | ERR_FATAL;
5404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005405 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005406
5407 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005408 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5409 free(curproxy->conn_src.iface_name);
5410 curproxy->conn_src.iface_name = NULL;
5411 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005412
Willy Tarreau902636f2013-03-10 19:44:48 +01005413 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005414 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005415 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005416 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005417 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005418 goto out;
5419 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005420
5421 proto = protocol_by_family(sk->ss_family);
5422 if (!proto || !proto->connect) {
5423 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005424 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005425 err_code |= ERR_ALERT | ERR_FATAL;
5426 goto out;
5427 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005428
5429 if (port1 != port2) {
5430 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5431 file, linenum, args[0], args[1]);
5432 err_code |= ERR_ALERT | ERR_FATAL;
5433 goto out;
5434 }
5435
Willy Tarreauef9a3602012-12-08 22:29:20 +01005436 curproxy->conn_src.source_addr = *sk;
5437 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005438
5439 cur_arg = 2;
5440 while (*(args[cur_arg])) {
5441 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005442#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5443#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005444 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005445 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5446 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005447 err_code |= ERR_ALERT | ERR_FATAL;
5448 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005449 }
5450#endif
5451 if (!*args[cur_arg + 1]) {
5452 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5453 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005454 err_code |= ERR_ALERT | ERR_FATAL;
5455 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005456 }
5457
5458 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005459 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5460 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005461 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005462 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5463 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005464 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5465 char *name, *end;
5466
5467 name = args[cur_arg+1] + 7;
5468 while (isspace(*name))
5469 name++;
5470
5471 end = name;
5472 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5473 end++;
5474
Willy Tarreauef9a3602012-12-08 22:29:20 +01005475 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5476 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5477 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5478 curproxy->conn_src.bind_hdr_len = end - name;
5479 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5480 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5481 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005482
5483 /* now look for an occurrence number */
5484 while (isspace(*end))
5485 end++;
5486 if (*end == ',') {
5487 end++;
5488 name = end;
5489 if (*end == '-')
5490 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005491 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005492 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005493 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005494 }
5495
Willy Tarreauef9a3602012-12-08 22:29:20 +01005496 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005497 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5498 " occurrences values smaller than %d.\n",
5499 file, linenum, MAX_HDR_HISTORY);
5500 err_code |= ERR_ALERT | ERR_FATAL;
5501 goto out;
5502 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005503 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005504 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005505
Willy Tarreau902636f2013-03-10 19:44:48 +01005506 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005507 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005508 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005509 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005510 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005511 goto out;
5512 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005513
5514 proto = protocol_by_family(sk->ss_family);
5515 if (!proto || !proto->connect) {
5516 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5517 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005518 err_code |= ERR_ALERT | ERR_FATAL;
5519 goto out;
5520 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005521
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005522 if (port1 != port2) {
5523 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5524 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005525 err_code |= ERR_ALERT | ERR_FATAL;
5526 goto out;
5527 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005528 curproxy->conn_src.tproxy_addr = *sk;
5529 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005530 }
5531 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005532#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005533 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005534#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005535#else /* no TPROXY support */
5536 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005537 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005538 err_code |= ERR_ALERT | ERR_FATAL;
5539 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005540#endif
5541 cur_arg += 2;
5542 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005543 }
5544
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005545 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5546#ifdef SO_BINDTODEVICE
5547 if (!*args[cur_arg + 1]) {
5548 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5549 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005550 err_code |= ERR_ALERT | ERR_FATAL;
5551 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005552 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005553 free(curproxy->conn_src.iface_name);
5554 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5555 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005556 global.last_checks |= LSTCHK_NETADM;
5557#else
5558 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5559 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005560 err_code |= ERR_ALERT | ERR_FATAL;
5561 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005562#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005563 cur_arg += 2;
5564 continue;
5565 }
5566 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005567 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005568 err_code |= ERR_ALERT | ERR_FATAL;
5569 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005570 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005571 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005572 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5573 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5574 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005575 err_code |= ERR_ALERT | ERR_FATAL;
5576 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005578 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005579 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005580 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5581 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005582 err_code |= ERR_ALERT | ERR_FATAL;
5583 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005584 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005585
5586 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005587 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005588 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005589 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005591 }
5592 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005593 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005594 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005595 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005596 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005598 }
5599 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005600 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005601 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005602 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005603 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605 }
5606 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005607 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005608 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005609 args[0], args[1], NULL, (const char **)args+2);
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], "reqallow")) { /* allow a request if a header matches this 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_ALLOW, 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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005620 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit 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_TARPIT, 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 Tarreaub8750a82006-09-03 09:56:00 +02005626 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005627 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
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_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005630 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005631 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005632 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005633
5634 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5635 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 +01005636 }
5637 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005638 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005639 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005640 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005641 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005642 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005643
5644 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5645 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 +01005646 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005647 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005648 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005649 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5650 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005651 err_code |= ERR_ALERT | ERR_FATAL;
5652 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005653 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005654
5655 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005656 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005657 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005658 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005659 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005660 }
5661 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005662 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005663 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005664 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005665 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005666 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005667 }
5668 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005669 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005670 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005671 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005672 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005674 }
5675 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005676 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005677 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005678 args[0], args[1], NULL, (const char **)args+2);
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], "reqiallow")) { /* allow a request if a header matches this 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_ALLOW, 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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005689 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit 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_TARPIT, 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 Tarreaub8750a82006-09-03 09:56:00 +02005695 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005696 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005697 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005698
Willy Tarreaubaaee002006-06-26 02:48:02 +02005699 if (curproxy == &defproxy) {
5700 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005701 err_code |= ERR_ALERT | ERR_FATAL;
5702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005703 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005704 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005705 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005706
Willy Tarreaubaaee002006-06-26 02:48:02 +02005707 if (*(args[1]) == 0) {
5708 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005709 err_code |= ERR_ALERT | ERR_FATAL;
5710 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005711 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005712
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005713 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005714 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5715 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5716 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005717 err_code |= ERR_ALERT | ERR_FATAL;
5718 goto out;
5719 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005720 err_code |= warnif_cond_conflicts(cond,
5721 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5722 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005723 }
5724 else if (*args[2]) {
5725 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5726 file, linenum, args[0], args[2]);
5727 err_code |= ERR_ALERT | ERR_FATAL;
5728 goto out;
5729 }
5730
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005731 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005732 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005733 wl->s = strdup(args[1]);
5734 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005735 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005736 }
5737 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005738 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005739 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5740 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005741 err_code |= ERR_ALERT | ERR_FATAL;
5742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005743 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005744
Willy Tarreauade5ec42010-01-28 19:33:49 +01005745 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005746 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005747 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005748 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005750 }
5751 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005752 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005753 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005754 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005755 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005757 }
5758 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005759 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005760 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005761 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005762 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005764 }
5765 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005766 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005767 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5768 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005769 err_code |= ERR_ALERT | ERR_FATAL;
5770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771 }
5772
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_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005775 args[0], args[1], args[2], (const char **)args+3);
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], "rspidel")) { /* delete response header from a regex ignoring case */
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_REMOVE, REG_ICASE,
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], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005787 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005788 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005789 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005790 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792 }
5793 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005794 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005795
Willy Tarreaubaaee002006-06-26 02:48:02 +02005796 if (curproxy == &defproxy) {
5797 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005798 err_code |= ERR_ALERT | ERR_FATAL;
5799 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005800 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005801 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005802 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005803
Willy Tarreaubaaee002006-06-26 02:48:02 +02005804 if (*(args[1]) == 0) {
5805 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005806 err_code |= ERR_ALERT | ERR_FATAL;
5807 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005808 }
5809
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005810 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005811 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5812 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5813 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005814 err_code |= ERR_ALERT | ERR_FATAL;
5815 goto out;
5816 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005817 err_code |= warnif_cond_conflicts(cond,
5818 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5819 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005820 }
5821 else if (*args[2]) {
5822 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5823 file, linenum, args[0], args[2]);
5824 err_code |= ERR_ALERT | ERR_FATAL;
5825 goto out;
5826 }
5827
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005828 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005829 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005830 wl->s = strdup(args[1]);
5831 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005832 }
5833 else if (!strcmp(args[0], "errorloc") ||
5834 !strcmp(args[0], "errorloc302") ||
5835 !strcmp(args[0], "errorloc303")) { /* error location */
5836 int errnum, errlen;
5837 char *err;
5838
Willy Tarreau977b8e42006-12-29 14:19:17 +01005839 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005840 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005841
Willy Tarreaubaaee002006-06-26 02:48:02 +02005842 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005843 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005844 err_code |= ERR_ALERT | ERR_FATAL;
5845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005846 }
5847
5848 errnum = atol(args[1]);
5849 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005850 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5851 err = malloc(errlen);
5852 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005853 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005854 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5855 err = malloc(errlen);
5856 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005857 }
5858
Willy Tarreau0f772532006-12-23 20:51:41 +01005859 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5860 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005861 chunk_destroy(&curproxy->errmsg[rc]);
5862 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005863 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005864 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005865 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005866
5867 if (rc >= HTTP_ERR_SIZE) {
5868 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5869 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005870 free(err);
5871 }
5872 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005873 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5874 int errnum, errlen, fd;
5875 char *err;
5876 struct stat stat;
5877
5878 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005879 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005880
5881 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005882 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005883 err_code |= ERR_ALERT | ERR_FATAL;
5884 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005885 }
5886
5887 fd = open(args[2], O_RDONLY);
5888 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5889 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5890 file, linenum, args[2], args[1]);
5891 if (fd >= 0)
5892 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005893 err_code |= ERR_ALERT | ERR_FATAL;
5894 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005895 }
5896
Willy Tarreau27a674e2009-08-17 07:23:33 +02005897 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005898 errlen = stat.st_size;
5899 } else {
5900 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005901 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005902 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005903 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005904 }
5905
5906 err = malloc(errlen); /* malloc() must succeed during parsing */
5907 errnum = read(fd, err, errlen);
5908 if (errnum != errlen) {
5909 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5910 file, linenum, args[2], args[1]);
5911 close(fd);
5912 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005913 err_code |= ERR_ALERT | ERR_FATAL;
5914 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005915 }
5916 close(fd);
5917
5918 errnum = atol(args[1]);
5919 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5920 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005921 chunk_destroy(&curproxy->errmsg[rc]);
5922 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005923 break;
5924 }
5925 }
5926
5927 if (rc >= HTTP_ERR_SIZE) {
5928 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5929 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005930 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005931 free(err);
5932 }
5933 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005934 else if (!strcmp(args[0], "compression")) {
5935 struct comp *comp;
5936 if (curproxy->comp == NULL) {
5937 comp = calloc(1, sizeof(struct comp));
5938 curproxy->comp = comp;
5939 } else {
5940 comp = curproxy->comp;
5941 }
5942
5943 if (!strcmp(args[1], "algo")) {
5944 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005945 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005946
William Lallemand82fe75c2012-10-23 10:25:10 +02005947 cur_arg = 2;
5948 if (!*args[cur_arg]) {
5949 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5950 file, linenum, args[0]);
5951 err_code |= ERR_ALERT | ERR_FATAL;
5952 goto out;
5953 }
5954 while (*(args[cur_arg])) {
5955 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5956 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5957 file, linenum, args[0], args[cur_arg]);
5958 err_code |= ERR_ALERT | ERR_FATAL;
5959 goto out;
5960 }
William Lallemand552df672012-11-07 13:21:47 +01005961 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5962 curproxy->comp->algos->end(&ctx);
5963 } else {
5964 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5965 file, linenum, args[0], args[cur_arg]);
5966 err_code |= ERR_ALERT | ERR_FATAL;
5967 goto out;
5968 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005969 cur_arg ++;
5970 continue;
5971 }
5972 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005973 else if (!strcmp(args[1], "offload")) {
5974 comp->offload = 1;
5975 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005976 else if (!strcmp(args[1], "type")) {
5977 int cur_arg;
5978 cur_arg = 2;
5979 if (!*args[cur_arg]) {
5980 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5981 file, linenum, args[0]);
5982 err_code |= ERR_ALERT | ERR_FATAL;
5983 goto out;
5984 }
5985 while (*(args[cur_arg])) {
5986 comp_append_type(comp, args[cur_arg]);
5987 cur_arg ++;
5988 continue;
5989 }
5990 }
5991 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005992 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005993 file, linenum, args[0]);
5994 err_code |= ERR_ALERT | ERR_FATAL;
5995 goto out;
5996 }
5997 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005998 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005999 struct cfg_kw_list *kwl;
6000 int index;
6001
6002 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6003 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6004 if (kwl->kw[index].section != CFG_LISTEN)
6005 continue;
6006 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6007 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006008 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006009 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006010 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006011 err_code |= ERR_ALERT | ERR_FATAL;
6012 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006013 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006014 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006015 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006016 err_code |= ERR_WARN;
6017 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006018 }
Willy Tarreau93893792009-07-23 13:19:11 +02006019 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006020 }
6021 }
6022 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006023
Willy Tarreau6daf3432008-01-22 16:44:08 +01006024 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006025 err_code |= ERR_ALERT | ERR_FATAL;
6026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006027 }
Willy Tarreau93893792009-07-23 13:19:11 +02006028 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006029 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006030 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006031}
6032
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006033int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006034cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6035{
6036#ifdef CONFIG_HAP_NS
6037 const char *err;
6038 const char *item = args[0];
6039
6040 if (!strcmp(item, "namespace_list")) {
6041 return 0;
6042 }
6043 else if (!strcmp(item, "namespace")) {
6044 size_t idx = 1;
6045 const char *current;
6046 while (*(current = args[idx++])) {
6047 err = invalid_char(current);
6048 if (err) {
6049 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6050 file, linenum, *err, item, current);
6051 return ERR_ALERT | ERR_FATAL;
6052 }
6053
6054 if (netns_store_lookup(current, strlen(current))) {
6055 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6056 file, linenum, current);
6057 return ERR_ALERT | ERR_FATAL;
6058 }
6059 if (!netns_store_insert(current)) {
6060 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6061 file, linenum, current);
6062 return ERR_ALERT | ERR_FATAL;
6063 }
6064 }
6065 }
6066
6067 return 0;
6068#else
6069 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6070 file, linenum);
6071 return ERR_ALERT | ERR_FATAL;
6072#endif
6073}
6074
6075int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006076cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6077{
6078
6079 int err_code = 0;
6080 const char *err;
6081
6082 if (!strcmp(args[0], "userlist")) { /* new userlist */
6083 struct userlist *newul;
6084
6085 if (!*args[1]) {
6086 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6087 file, linenum, args[0]);
6088 err_code |= ERR_ALERT | ERR_FATAL;
6089 goto out;
6090 }
6091
6092 err = invalid_char(args[1]);
6093 if (err) {
6094 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6095 file, linenum, *err, args[0], args[1]);
6096 err_code |= ERR_ALERT | ERR_FATAL;
6097 goto out;
6098 }
6099
6100 for (newul = userlist; newul; newul = newul->next)
6101 if (!strcmp(newul->name, args[1])) {
6102 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6103 file, linenum, args[1]);
6104 err_code |= ERR_WARN;
6105 goto out;
6106 }
6107
6108 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6109 if (!newul) {
6110 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6111 err_code |= ERR_ALERT | ERR_ABORT;
6112 goto out;
6113 }
6114
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006115 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006116 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006117 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6118 err_code |= ERR_ALERT | ERR_ABORT;
6119 goto out;
6120 }
6121
6122 newul->next = userlist;
6123 userlist = newul;
6124
6125 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006126 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006127 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006128 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006129
6130 if (!*args[1]) {
6131 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6132 file, linenum, args[0]);
6133 err_code |= ERR_ALERT | ERR_FATAL;
6134 goto out;
6135 }
6136
6137 err = invalid_char(args[1]);
6138 if (err) {
6139 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6140 file, linenum, *err, args[0], args[1]);
6141 err_code |= ERR_ALERT | ERR_FATAL;
6142 goto out;
6143 }
6144
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006145 for (ag = userlist->groups; ag; ag = ag->next)
6146 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006147 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6148 file, linenum, args[1], userlist->name);
6149 err_code |= ERR_ALERT;
6150 goto out;
6151 }
6152
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006153 ag = calloc(1, sizeof(*ag));
6154 if (!ag) {
6155 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6156 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006157 goto out;
6158 }
6159
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006160 ag->name = strdup(args[1]);
6161 if (!ag) {
6162 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6163 err_code |= ERR_ALERT | ERR_ABORT;
6164 goto out;
6165 }
6166
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006167 cur_arg = 2;
6168
6169 while (*args[cur_arg]) {
6170 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006171 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006172 cur_arg += 2;
6173 continue;
6174 } else {
6175 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6176 file, linenum, args[0]);
6177 err_code |= ERR_ALERT | ERR_FATAL;
6178 goto out;
6179 }
6180 }
6181
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006182 ag->next = userlist->groups;
6183 userlist->groups = ag;
6184
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006185 } else if (!strcmp(args[0], "user")) { /* new user */
6186 struct auth_users *newuser;
6187 int cur_arg;
6188
6189 if (!*args[1]) {
6190 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6191 file, linenum, args[0]);
6192 err_code |= ERR_ALERT | ERR_FATAL;
6193 goto out;
6194 }
6195
6196 for (newuser = userlist->users; newuser; newuser = newuser->next)
6197 if (!strcmp(newuser->user, args[1])) {
6198 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6199 file, linenum, args[1], userlist->name);
6200 err_code |= ERR_ALERT;
6201 goto out;
6202 }
6203
6204 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6205 if (!newuser) {
6206 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6207 err_code |= ERR_ALERT | ERR_ABORT;
6208 goto out;
6209 }
6210
6211 newuser->user = strdup(args[1]);
6212
6213 newuser->next = userlist->users;
6214 userlist->users = newuser;
6215
6216 cur_arg = 2;
6217
6218 while (*args[cur_arg]) {
6219 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006220#ifdef CONFIG_HAP_CRYPT
6221 if (!crypt("", args[cur_arg + 1])) {
6222 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6223 file, linenum, newuser->user);
6224 err_code |= ERR_ALERT | ERR_FATAL;
6225 goto out;
6226 }
6227#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006228 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6229 file, linenum);
6230 err_code |= ERR_ALERT;
6231#endif
6232 newuser->pass = strdup(args[cur_arg + 1]);
6233 cur_arg += 2;
6234 continue;
6235 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6236 newuser->pass = strdup(args[cur_arg + 1]);
6237 newuser->flags |= AU_O_INSECURE;
6238 cur_arg += 2;
6239 continue;
6240 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006241 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006242 cur_arg += 2;
6243 continue;
6244 } else {
6245 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6246 file, linenum, args[0]);
6247 err_code |= ERR_ALERT | ERR_FATAL;
6248 goto out;
6249 }
6250 }
6251 } else {
6252 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6253 err_code |= ERR_ALERT | ERR_FATAL;
6254 }
6255
6256out:
6257 return err_code;
6258}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006259
6260/*
6261 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006262 * Returns the error code, 0 if OK, or any combination of :
6263 * - ERR_ABORT: must abort ASAP
6264 * - ERR_FATAL: we can continue parsing but not start the service
6265 * - ERR_WARN: a warning has been emitted
6266 * - ERR_ALERT: an alert has been emitted
6267 * Only the two first ones can stop processing, the two others are just
6268 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006269 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006270int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006271{
William Lallemand64e84512015-05-12 14:25:37 +02006272 char *thisline;
6273 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006274 FILE *f;
6275 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006276 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006277 struct cfg_section *cs = NULL;
6278 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006279 int readbytes = 0;
6280
6281 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006282 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006283 return -1;
6284 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006285
6286 /* Register internal sections */
6287 if (!cfg_register_section("listen", cfg_parse_listen) ||
6288 !cfg_register_section("frontend", cfg_parse_listen) ||
6289 !cfg_register_section("backend", cfg_parse_listen) ||
6290 !cfg_register_section("ruleset", cfg_parse_listen) ||
6291 !cfg_register_section("defaults", cfg_parse_listen) ||
6292 !cfg_register_section("global", cfg_parse_global) ||
6293 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006294 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006295 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006296 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006297 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006298
Willy Tarreaubaaee002006-06-26 02:48:02 +02006299 if ((f=fopen(file,"r")) == NULL)
6300 return -1;
6301
William Lallemandb2f07452015-05-12 14:27:13 +02006302next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006303 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006304 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006305 char *end;
6306 char *args[MAX_LINE_ARGS + 1];
6307 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006308 int dquote = 0; /* double quote */
6309 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006310
Willy Tarreaubaaee002006-06-26 02:48:02 +02006311 linenum++;
6312
6313 end = line + strlen(line);
6314
William Lallemand64e84512015-05-12 14:25:37 +02006315 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006316 /* Check if we reached the limit and the last char is not \n.
6317 * Watch out for the last line without the terminating '\n'!
6318 */
William Lallemand64e84512015-05-12 14:25:37 +02006319 char *newline;
6320 int newlinesize = linesize * 2;
6321
6322 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6323 if (newline == NULL) {
6324 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6325 file, linenum);
6326 err_code |= ERR_ALERT | ERR_FATAL;
6327 continue;
6328 }
6329
6330 readbytes = linesize - 1;
6331 linesize = newlinesize;
6332 thisline = newline;
6333 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006334 }
6335
William Lallemand64e84512015-05-12 14:25:37 +02006336 readbytes = 0;
6337
Willy Tarreaubaaee002006-06-26 02:48:02 +02006338 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006339 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006340 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006341
Willy Tarreaubaaee002006-06-26 02:48:02 +02006342 arg = 0;
6343 args[arg] = line;
6344
6345 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006346 if (*line == '"' && !squote) { /* double quote outside single quotes */
6347 if (dquote)
6348 dquote = 0;
6349 else
6350 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006351 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006352 end--;
6353 }
6354 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6355 if (squote)
6356 squote = 0;
6357 else
6358 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006359 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006360 end--;
6361 }
6362 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006363 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6364 * C equivalent value. Other combinations left unchanged (eg: \1).
6365 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006366 int skip = 0;
6367 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6368 *line = line[1];
6369 skip = 1;
6370 }
6371 else if (line[1] == 'r') {
6372 *line = '\r';
6373 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006374 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006375 else if (line[1] == 'n') {
6376 *line = '\n';
6377 skip = 1;
6378 }
6379 else if (line[1] == 't') {
6380 *line = '\t';
6381 skip = 1;
6382 }
6383 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006384 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006385 unsigned char hex1, hex2;
6386 hex1 = toupper(line[2]) - '0';
6387 hex2 = toupper(line[3]) - '0';
6388 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6389 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6390 *line = (hex1<<4) + hex2;
6391 skip = 3;
6392 }
6393 else {
6394 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006395 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006396 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006397 } else if (line[1] == '"') {
6398 *line = '"';
6399 skip = 1;
6400 } else if (line[1] == '\'') {
6401 *line = '\'';
6402 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006403 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6404 *line = '$';
6405 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006406 }
6407 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006408 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006409 end -= skip;
6410 }
6411 line++;
6412 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006413 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006414 /* end of string, end of loop */
6415 *line = 0;
6416 break;
6417 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006418 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006419 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006420 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006421 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006422 line++;
6423 args[++arg] = line;
6424 }
William Lallemandb2f07452015-05-12 14:27:13 +02006425 else if (dquote && *line == '$') {
6426 /* environment variables are evaluated inside double quotes */
6427 char *var_beg;
6428 char *var_end;
6429 char save_char;
6430 char *value;
6431 int val_len;
6432 int newlinesize;
6433 int braces = 0;
6434
6435 var_beg = line + 1;
6436 var_end = var_beg;
6437
6438 if (*var_beg == '{') {
6439 var_beg++;
6440 var_end++;
6441 braces = 1;
6442 }
6443
6444 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6445 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6446 err_code |= ERR_ALERT | ERR_FATAL;
6447 goto next_line; /* skip current line */
6448 }
6449
6450 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6451 var_end++;
6452
6453 save_char = *var_end;
6454 *var_end = '\0';
6455 value = getenv(var_beg);
6456 *var_end = save_char;
6457 val_len = value ? strlen(value) : 0;
6458
6459 if (braces) {
6460 if (*var_end == '}') {
6461 var_end++;
6462 braces = 0;
6463 } else {
6464 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
6465 err_code |= ERR_ALERT | ERR_FATAL;
6466 goto next_line; /* skip current line */
6467 }
6468 }
6469
6470 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
6471
6472 /* if not enough space in thisline */
6473 if (newlinesize > linesize) {
6474 char *newline;
6475
6476 newline = realloc(thisline, newlinesize * sizeof(*thisline));
6477 if (newline == NULL) {
6478 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
6479 err_code |= ERR_ALERT | ERR_FATAL;
6480 goto next_line; /* slip current line */
6481 }
6482 /* recompute pointers if realloc returns a new pointer */
6483 if (newline != thisline) {
6484 int i;
6485 int diff;
6486
6487 for (i = 0; i <= arg; i++) {
6488 diff = args[i] - thisline;
6489 args[i] = newline + diff;
6490 }
6491
6492 diff = var_end - thisline;
6493 var_end = newline + diff;
6494 diff = end - thisline;
6495 end = newline + diff;
6496 diff = line - thisline;
6497 line = newline + diff;
6498 thisline = newline;
6499 }
6500 linesize = newlinesize;
6501 }
6502
6503 /* insert value inside the line */
6504 memmove(line + val_len, var_end, end - var_end + 1);
6505 memcpy(line, value, val_len);
6506 end += val_len - (var_end - line);
6507 line += val_len;
6508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006509 else {
6510 line++;
6511 }
6512 }
William Lallemandb2f07452015-05-12 14:27:13 +02006513
William Lallemandf9873ba2015-05-05 17:37:14 +02006514 if (dquote) {
6515 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
6516 err_code |= ERR_ALERT | ERR_FATAL;
6517 }
6518
6519 if (squote) {
6520 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
6521 err_code |= ERR_ALERT | ERR_FATAL;
6522 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006523
6524 /* empty line */
6525 if (!**args)
6526 continue;
6527
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006528 if (*line) {
6529 /* we had to stop due to too many args.
6530 * Let's terminate the string, print the offending part then cut the
6531 * last arg.
6532 */
6533 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6534 line++;
6535 *line = '\0';
6536
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006537 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006538 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006539 err_code |= ERR_ALERT | ERR_FATAL;
6540 args[arg] = line;
6541 }
6542
Willy Tarreau540abe42007-05-02 20:50:16 +02006543 /* zero out remaining args and ensure that at least one entry
6544 * is zeroed out.
6545 */
6546 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006547 args[arg] = line;
6548 }
6549
Willy Tarreau3842f002009-06-14 11:39:52 +02006550 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006551 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006552 char *tmp;
6553
Willy Tarreau3842f002009-06-14 11:39:52 +02006554 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006555 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006556 for (arg=0; *args[arg+1]; arg++)
6557 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006558 *tmp = '\0'; // fix the next arg to \0
6559 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006560 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006561 else if (!strcmp(args[0], "default")) {
6562 kwm = KWM_DEF;
6563 for (arg=0; *args[arg+1]; arg++)
6564 args[arg] = args[arg+1]; // shift args after inversion
6565 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006566
William Lallemand0f99e342011-10-12 17:50:54 +02006567 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6568 strcmp(args[0], "log") != 0) {
6569 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006570 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006571 }
6572
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006573 /* detect section start */
6574 list_for_each_entry(ics, &sections, list) {
6575 if (strcmp(args[0], ics->section_name) == 0) {
6576 cursection = ics->section_name;
6577 cs = ics;
6578 break;
6579 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006580 }
6581
Willy Tarreaubaaee002006-06-26 02:48:02 +02006582 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006583 if (cs)
6584 err_code |= cs->section_parser(file, linenum, args, kwm);
6585 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006586 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006587 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006588 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006589
6590 if (err_code & ERR_ABORT)
6591 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006592 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006593 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02006594 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006595 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006596 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006597}
6598
Willy Tarreau64ab6072014-09-16 12:17:36 +02006599/* This function propagates processes from frontend <from> to backend <to> so
6600 * that it is always guaranteed that a backend pointed to by a frontend is
6601 * bound to all of its processes. After that, if the target is a "listen"
6602 * instance, the function recursively descends the target's own targets along
6603 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6604 * checked first to ensure that <to> is already bound to all processes of
6605 * <from>, there is no risk of looping and we ensure to follow the shortest
6606 * path to the destination.
6607 *
6608 * It is possible to set <to> to NULL for the first call so that the function
6609 * takes care of visiting the initial frontend in <from>.
6610 *
6611 * It is important to note that the function relies on the fact that all names
6612 * have already been resolved.
6613 */
6614void propagate_processes(struct proxy *from, struct proxy *to)
6615{
6616 struct switching_rule *rule;
6617 struct hdr_exp *exp;
6618
6619 if (to) {
6620 /* check whether we need to go down */
6621 if (from->bind_proc &&
6622 (from->bind_proc & to->bind_proc) == from->bind_proc)
6623 return;
6624
6625 if (!from->bind_proc && !to->bind_proc)
6626 return;
6627
6628 to->bind_proc = from->bind_proc ?
6629 (to->bind_proc | from->bind_proc) : 0;
6630
6631 /* now propagate down */
6632 from = to;
6633 }
6634
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006635 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006636 return;
6637
Willy Tarreauf6b70012014-12-18 14:00:43 +01006638 if (from->state == PR_STSTOPPED)
6639 return;
6640
Willy Tarreau64ab6072014-09-16 12:17:36 +02006641 /* default_backend */
6642 if (from->defbe.be)
6643 propagate_processes(from, from->defbe.be);
6644
6645 /* use_backend */
6646 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006647 if (rule->dynamic)
6648 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006649 to = rule->be.backend;
6650 propagate_processes(from, to);
6651 }
6652
6653 /* reqsetbe */
6654 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6655 if (exp->action != ACT_SETBE)
6656 continue;
6657 to = (struct proxy *)exp->replace;
6658 propagate_processes(from, to);
6659 }
6660}
6661
Willy Tarreaubb925012009-07-23 13:36:36 +02006662/*
6663 * Returns the error code, 0 if OK, or any combination of :
6664 * - ERR_ABORT: must abort ASAP
6665 * - ERR_FATAL: we can continue parsing but not start the service
6666 * - ERR_WARN: a warning has been emitted
6667 * - ERR_ALERT: an alert has been emitted
6668 * Only the two first ones can stop processing, the two others are just
6669 * indicators.
6670 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006671int check_config_validity()
6672{
6673 int cfgerr = 0;
6674 struct proxy *curproxy = NULL;
6675 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006676 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006677 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006678 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006679
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006680 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006681 /*
6682 * Now, check for the integrity of all that we have collected.
6683 */
6684
6685 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006686 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006687
Willy Tarreau193b8c62012-11-22 00:17:38 +01006688 if (!global.tune.max_http_hdr)
6689 global.tune.max_http_hdr = MAX_HTTP_HDR;
6690
6691 if (!global.tune.cookie_len)
6692 global.tune.cookie_len = CAPTURE_LEN;
6693
6694 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6695
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006696 /* Post initialisation of the users and groups lists. */
6697 err_code = userlist_postinit();
6698 if (err_code != ERR_NONE)
6699 goto out;
6700
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006701 /* first, we will invert the proxy list order */
6702 curproxy = NULL;
6703 while (proxy) {
6704 struct proxy *next;
6705
6706 next = proxy->next;
6707 proxy->next = curproxy;
6708 curproxy = proxy;
6709 if (!next)
6710 break;
6711 proxy = next;
6712 }
6713
Willy Tarreau419ead82014-09-16 13:41:21 +02006714 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006715 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006716 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006717 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006718 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006719 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006720 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006721 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006722
Willy Tarreau050536d2012-10-04 08:47:34 +02006723 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006724 /* proxy ID not set, use automatic numbering with first
6725 * spare entry starting with next_pxid.
6726 */
6727 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6728 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6729 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006730 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006731 next_pxid++;
6732
Willy Tarreau55ea7572007-06-17 19:56:27 +02006733
Willy Tarreaubaaee002006-06-26 02:48:02 +02006734 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006735 /* ensure we don't keep listeners uselessly bound */
6736 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02006737 free((void *)curproxy->table.peers.name);
6738 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006739 continue;
6740 }
6741
Willy Tarreau102df612014-05-07 23:56:38 +02006742 /* Check multi-process mode compatibility for the current proxy */
6743
6744 if (curproxy->bind_proc) {
6745 /* an explicit bind-process was specified, let's check how many
6746 * processes remain.
6747 */
6748 nbproc = popcount(curproxy->bind_proc);
6749
6750 curproxy->bind_proc &= nbits(global.nbproc);
6751 if (!curproxy->bind_proc && nbproc == 1) {
6752 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);
6753 curproxy->bind_proc = 1;
6754 }
6755 else if (!curproxy->bind_proc && nbproc > 1) {
6756 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);
6757 curproxy->bind_proc = 0;
6758 }
6759 }
6760
Willy Tarreau3d209582014-05-09 17:06:11 +02006761 /* check and reduce the bind-proc of each listener */
6762 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6763 unsigned long mask;
6764
6765 if (!bind_conf->bind_proc)
6766 continue;
6767
6768 mask = nbits(global.nbproc);
6769 if (curproxy->bind_proc)
6770 mask &= curproxy->bind_proc;
6771 /* mask cannot be null here thanks to the previous checks */
6772
6773 nbproc = popcount(bind_conf->bind_proc);
6774 bind_conf->bind_proc &= mask;
6775
6776 if (!bind_conf->bind_proc && nbproc == 1) {
6777 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",
6778 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6779 bind_conf->bind_proc = mask & ~(mask - 1);
6780 }
6781 else if (!bind_conf->bind_proc && nbproc > 1) {
6782 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",
6783 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6784 bind_conf->bind_proc = 0;
6785 }
6786 }
6787
Willy Tarreauff01a212009-03-15 13:46:16 +01006788 switch (curproxy->mode) {
6789 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006790 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006791 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006792 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6793 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006794 cfgerr++;
6795 }
6796
6797 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006798 Warning("config : servers will be ignored for %s '%s'.\n",
6799 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006800 break;
6801
6802 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006803 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006804 break;
6805
6806 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006807 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006808 break;
6809 }
6810
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006811 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006812 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006813 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006814 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6815 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006816 cfgerr++;
6817 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006818#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006819 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006820 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6821 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006822 cfgerr++;
6823 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006824#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006825 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006826 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6827 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006828 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006829 }
6830 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006831 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006832 /* If no LB algo is set in a backend, and we're not in
6833 * transparent mode, dispatch mode nor proxy mode, we
6834 * want to use balance roundrobin by default.
6835 */
6836 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6837 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006838 }
6839 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006840
Willy Tarreau1620ec32011-08-06 17:05:02 +02006841 if (curproxy->options & PR_O_DISPATCH)
6842 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6843 else if (curproxy->options & PR_O_HTTP_PROXY)
6844 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6845 else if (curproxy->options & PR_O_TRANSP)
6846 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006847
Willy Tarreau1620ec32011-08-06 17:05:02 +02006848 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6849 if (curproxy->options & PR_O_DISABLE404) {
6850 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6851 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6852 err_code |= ERR_WARN;
6853 curproxy->options &= ~PR_O_DISABLE404;
6854 }
6855 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6856 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6857 "send-state", proxy_type_str(curproxy), curproxy->id);
6858 err_code |= ERR_WARN;
6859 curproxy->options &= ~PR_O2_CHK_SNDST;
6860 }
Willy Tarreauef781042010-01-27 11:53:01 +01006861 }
6862
Simon Horman98637e52014-06-20 12:30:16 +09006863 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6864 if (!global.external_check) {
6865 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6866 curproxy->id, "option external-check");
6867 cfgerr++;
6868 }
6869 if (!curproxy->check_command) {
6870 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6871 curproxy->id, "option external-check");
6872 cfgerr++;
6873 }
6874 }
6875
Simon Horman64e34162015-02-06 11:11:57 +09006876 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006877 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
6878 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09006879 "'email-alert from', 'email-alert level' 'email-alert mailer', "
6880 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006881 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
6882 "to be present).\n",
6883 proxy_type_str(curproxy), curproxy->id);
6884 err_code |= ERR_WARN;
6885 free_email_alert(curproxy);
6886 }
6887 if (!curproxy->email_alert.myhostname)
6888 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09006889 }
6890
Simon Horman98637e52014-06-20 12:30:16 +09006891 if (curproxy->check_command) {
6892 int clear = 0;
6893 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6894 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6895 "external-check command", proxy_type_str(curproxy), curproxy->id);
6896 err_code |= ERR_WARN;
6897 clear = 1;
6898 }
6899 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6900 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6901 curproxy->id, "external-check command");
6902 cfgerr++;
6903 }
6904 if (clear) {
6905 free(curproxy->check_command);
6906 curproxy->check_command = NULL;
6907 }
6908 }
6909
6910 if (curproxy->check_path) {
6911 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6912 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6913 "external-check path", proxy_type_str(curproxy), curproxy->id);
6914 err_code |= ERR_WARN;
6915 free(curproxy->check_path);
6916 curproxy->check_path = NULL;
6917 }
6918 }
6919
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006920 /* if a default backend was specified, let's find it */
6921 if (curproxy->defbe.name) {
6922 struct proxy *target;
6923
Alex Williams96532db2009-11-01 21:27:13 -05006924 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006925 if (!target) {
6926 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6927 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006928 cfgerr++;
6929 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006930 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6931 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006932 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006933 } else {
6934 free(curproxy->defbe.name);
6935 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006936
6937 /* Emit a warning if this proxy also has some servers */
6938 if (curproxy->srv) {
6939 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6940 curproxy->id);
6941 err_code |= ERR_WARN;
6942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006943 }
6944 }
6945
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006946 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006947 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6948 /* map jump target for ACT_SETBE in req_rep chain */
6949 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006950 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006951 struct proxy *target;
6952
Willy Tarreaua496b602006-12-17 23:15:24 +01006953 if (exp->action != ACT_SETBE)
6954 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006955
Alex Williams96532db2009-11-01 21:27:13 -05006956 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006957 if (!target) {
6958 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6959 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006960 cfgerr++;
6961 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006962 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6963 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006964 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006965 } else {
6966 free((void *)exp->replace);
6967 exp->replace = (const char *)target;
6968 }
6969 }
6970 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006971
6972 /* find the target proxy for 'use_backend' rules */
6973 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006974 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006975 struct logformat_node *node;
6976 char *pxname;
6977
6978 /* Try to parse the string as a log format expression. If the result
6979 * of the parsing is only one entry containing a simple string, then
6980 * it's a standard string corresponding to a static rule, thus the
6981 * parsing is cancelled and be.name is restored to be resolved.
6982 */
6983 pxname = rule->be.name;
6984 LIST_INIT(&rule->be.expr);
6985 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6986 curproxy->conf.args.file, curproxy->conf.args.line);
6987 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6988
6989 if (!LIST_ISEMPTY(&rule->be.expr)) {
6990 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6991 rule->dynamic = 1;
6992 free(pxname);
6993 continue;
6994 }
6995 /* simple string: free the expression and fall back to static rule */
6996 free(node->arg);
6997 free(node);
6998 }
6999
7000 rule->dynamic = 0;
7001 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007002
Alex Williams96532db2009-11-01 21:27:13 -05007003 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007004
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007005 if (!target) {
7006 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7007 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007008 cfgerr++;
7009 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007010 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7011 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007012 cfgerr++;
7013 } else {
7014 free((void *)rule->be.name);
7015 rule->be.backend = target;
7016 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007017 }
7018
Willy Tarreau64ab6072014-09-16 12:17:36 +02007019 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007020 list_for_each_entry(srule, &curproxy->server_rules, list) {
7021 struct server *target = findserver(curproxy, srule->srv.name);
7022
7023 if (!target) {
7024 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7025 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7026 cfgerr++;
7027 continue;
7028 }
7029 free((void *)srule->srv.name);
7030 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007031 }
7032
Emeric Brunb982a3d2010-01-04 15:45:53 +01007033 /* find the target table for 'stick' rules */
7034 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7035 struct proxy *target;
7036
Emeric Brun1d33b292010-01-04 15:47:17 +01007037 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7038 if (mrule->flags & STK_IS_STORE)
7039 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7040
Emeric Brunb982a3d2010-01-04 15:45:53 +01007041 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007042 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007043 else
7044 target = curproxy;
7045
7046 if (!target) {
7047 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7048 curproxy->id, mrule->table.name);
7049 cfgerr++;
7050 }
7051 else if (target->table.size == 0) {
7052 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7053 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7054 cfgerr++;
7055 }
Willy Tarreau12785782012-04-27 21:37:17 +02007056 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7057 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007058 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7059 cfgerr++;
7060 }
7061 else {
7062 free((void *)mrule->table.name);
7063 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007064 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007065 }
7066 }
7067
7068 /* find the target table for 'store response' rules */
7069 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7070 struct proxy *target;
7071
Emeric Brun1d33b292010-01-04 15:47:17 +01007072 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7073
Emeric Brunb982a3d2010-01-04 15:45:53 +01007074 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007075 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007076 else
7077 target = curproxy;
7078
7079 if (!target) {
7080 Alert("Proxy '%s': unable to find store table '%s'.\n",
7081 curproxy->id, mrule->table.name);
7082 cfgerr++;
7083 }
7084 else if (target->table.size == 0) {
7085 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7086 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7087 cfgerr++;
7088 }
Willy Tarreau12785782012-04-27 21:37:17 +02007089 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7090 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007091 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7092 cfgerr++;
7093 }
7094 else {
7095 free((void *)mrule->table.name);
7096 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007097 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007098 }
7099 }
7100
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007101 /* find the target table for 'tcp-request' layer 4 rules */
7102 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7103 struct proxy *target;
7104
Willy Tarreaub4c84932013-07-23 19:15:30 +02007105 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007106 continue;
7107
7108 if (trule->act_prm.trk_ctr.table.n)
7109 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
7110 else
7111 target = curproxy;
7112
7113 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007114 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7115 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007116 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007117 cfgerr++;
7118 }
7119 else if (target->table.size == 0) {
7120 Alert("Proxy '%s': table '%s' used but not configured.\n",
7121 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7122 cfgerr++;
7123 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007124 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7125 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7126 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 +01007127 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007128 cfgerr++;
7129 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007130 else {
7131 free(trule->act_prm.trk_ctr.table.n);
7132 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007133 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007134 * to pass a list of counters to track and allocate them right here using
7135 * stktable_alloc_data_type().
7136 */
7137 }
7138 }
7139
Willy Tarreaud1f96522010-08-03 19:34:32 +02007140 /* find the target table for 'tcp-request' layer 6 rules */
7141 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7142 struct proxy *target;
7143
Willy Tarreaub4c84932013-07-23 19:15:30 +02007144 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007145 continue;
7146
7147 if (trule->act_prm.trk_ctr.table.n)
7148 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
7149 else
7150 target = curproxy;
7151
7152 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007153 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7154 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007155 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007156 cfgerr++;
7157 }
7158 else if (target->table.size == 0) {
7159 Alert("Proxy '%s': table '%s' used but not configured.\n",
7160 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7161 cfgerr++;
7162 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007163 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7164 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7165 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 +01007166 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007167 cfgerr++;
7168 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007169 else {
7170 free(trule->act_prm.trk_ctr.table.n);
7171 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007172 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007173 * to pass a list of counters to track and allocate them right here using
7174 * stktable_alloc_data_type().
7175 */
7176 }
7177 }
7178
Willy Tarreau09448f72014-06-25 18:12:15 +02007179 /* find the target table for 'http-request' layer 7 rules */
7180 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7181 struct proxy *target;
7182
7183 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
7184 continue;
7185
7186 if (hrqrule->act_prm.trk_ctr.table.n)
7187 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
7188 else
7189 target = curproxy;
7190
7191 if (!target) {
7192 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7193 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
7194 http_req_trk_idx(hrqrule->action));
7195 cfgerr++;
7196 }
7197 else if (target->table.size == 0) {
7198 Alert("Proxy '%s': table '%s' used but not configured.\n",
7199 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
7200 cfgerr++;
7201 }
7202 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
7203 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7204 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
7205 http_req_trk_idx(hrqrule->action));
7206 cfgerr++;
7207 }
7208 else {
7209 free(hrqrule->act_prm.trk_ctr.table.n);
7210 hrqrule->act_prm.trk_ctr.table.t = &target->table;
7211 /* Note: if we decide to enhance the track-sc syntax, we may be able
7212 * to pass a list of counters to track and allocate them right here using
7213 * stktable_alloc_data_type().
7214 */
7215 }
7216 }
7217
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007218 /* move any "block" rules at the beginning of the http-request rules */
7219 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7220 /* insert block_rules into http_req_rules at the beginning */
7221 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7222 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7223 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7224 curproxy->http_req_rules.n = curproxy->block_rules.n;
7225 LIST_INIT(&curproxy->block_rules);
7226 }
7227
Emeric Brun32da3c42010-09-23 18:39:19 +02007228 if (curproxy->table.peers.name) {
7229 struct peers *curpeers = peers;
7230
7231 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7232 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7233 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007234 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007235 break;
7236 }
7237 }
7238
7239 if (!curpeers) {
7240 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7241 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007242 free((void *)curproxy->table.peers.name);
7243 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007244 cfgerr++;
7245 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007246 else if (curpeers->state == PR_STSTOPPED) {
7247 /* silently disable this peers section */
7248 curproxy->table.peers.p = NULL;
7249 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007250 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007251 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7252 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007253 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007254 cfgerr++;
7255 }
7256 }
7257
Simon Horman9dc49962015-01-30 11:22:59 +09007258
7259 if (curproxy->email_alert.mailers.name) {
7260 struct mailers *curmailers = mailers;
7261
7262 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7263 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7264 free(curproxy->email_alert.mailers.name);
7265 curproxy->email_alert.mailers.m = curmailers;
7266 curmailers->users++;
7267 break;
7268 }
7269 }
7270
7271 if (!curmailers) {
7272 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7273 curproxy->id, curproxy->email_alert.mailers.name);
7274 free_email_alert(curproxy);
7275 cfgerr++;
7276 }
7277 }
7278
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007279 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007280 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007281 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7282 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7283 "proxy", curproxy->id);
7284 cfgerr++;
7285 goto out_uri_auth_compat;
7286 }
7287
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007288 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007289 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007290 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007291 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007292
Willy Tarreau95fa4692010-02-01 13:05:50 +01007293 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7294 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007295
7296 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007297 uri_auth_compat_req[i++] = "realm";
7298 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7299 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007300
Willy Tarreau95fa4692010-02-01 13:05:50 +01007301 uri_auth_compat_req[i++] = "unless";
7302 uri_auth_compat_req[i++] = "{";
7303 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7304 uri_auth_compat_req[i++] = "}";
7305 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007306
Willy Tarreauff011f22011-01-06 17:51:27 +01007307 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7308 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007309 cfgerr++;
7310 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007311 }
7312
Willy Tarreauff011f22011-01-06 17:51:27 +01007313 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007314
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007315 if (curproxy->uri_auth->auth_realm) {
7316 free(curproxy->uri_auth->auth_realm);
7317 curproxy->uri_auth->auth_realm = NULL;
7318 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007319
7320 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007321 }
7322out_uri_auth_compat:
7323
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007324 /* compile the log format */
7325 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007326 if (curproxy->conf.logformat_string != default_http_log_format &&
7327 curproxy->conf.logformat_string != default_tcp_log_format &&
7328 curproxy->conf.logformat_string != clf_http_log_format)
7329 free(curproxy->conf.logformat_string);
7330 curproxy->conf.logformat_string = NULL;
7331 free(curproxy->conf.lfs_file);
7332 curproxy->conf.lfs_file = NULL;
7333 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007334 }
7335
Willy Tarreau62a61232013-04-12 18:13:46 +02007336 if (curproxy->conf.logformat_string) {
7337 curproxy->conf.args.ctx = ARGC_LOG;
7338 curproxy->conf.args.file = curproxy->conf.lfs_file;
7339 curproxy->conf.args.line = curproxy->conf.lfs_line;
7340 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007341 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007342 curproxy->conf.args.file = NULL;
7343 curproxy->conf.args.line = 0;
7344 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007345
Willy Tarreau62a61232013-04-12 18:13:46 +02007346 if (curproxy->conf.uniqueid_format_string) {
7347 curproxy->conf.args.ctx = ARGC_UIF;
7348 curproxy->conf.args.file = curproxy->conf.uif_file;
7349 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007350 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007351 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007352 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007353 curproxy->conf.args.file = NULL;
7354 curproxy->conf.args.line = 0;
7355 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007356
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007357 /* only now we can check if some args remain unresolved.
7358 * This must be done after the users and groups resolution.
7359 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007360 cfgerr += smp_resolve_args(curproxy);
7361 if (!cfgerr)
7362 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007363
Willy Tarreau2738a142006-07-08 17:28:09 +02007364 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007365 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007366 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007367 (!curproxy->timeout.connect ||
7368 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007369 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007370 " | While not properly invalid, you will certainly encounter various problems\n"
7371 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007372 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007373 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007374 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007375 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007376
Willy Tarreau1fa31262007-12-03 00:36:16 +01007377 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7378 * We must still support older configurations, so let's find out whether those
7379 * parameters have been set or must be copied from contimeouts.
7380 */
7381 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007382 if (!curproxy->timeout.tarpit ||
7383 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007384 /* tarpit timeout not set. We search in the following order:
7385 * default.tarpit, curr.connect, default.connect.
7386 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007387 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007388 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007389 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007390 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007391 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007392 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007393 }
7394 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007395 (!curproxy->timeout.queue ||
7396 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007397 /* queue timeout not set. We search in the following order:
7398 * default.queue, curr.connect, default.connect.
7399 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007400 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007401 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007402 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007403 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007404 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007405 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007406 }
7407 }
7408
Willy Tarreau1620ec32011-08-06 17:05:02 +02007409 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007410 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7411 curproxy->check_req = (char *)malloc(curproxy->check_len);
7412 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007413 }
7414
Willy Tarreau215663d2014-06-13 18:30:23 +02007415 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7416 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7417 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7418 proxy_type_str(curproxy), curproxy->id);
7419 err_code |= ERR_WARN;
7420 }
7421
Willy Tarreau193b8c62012-11-22 00:17:38 +01007422 /* ensure that cookie capture length is not too large */
7423 if (curproxy->capture_len >= global.tune.cookie_len) {
7424 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7425 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7426 err_code |= ERR_WARN;
7427 curproxy->capture_len = global.tune.cookie_len - 1;
7428 }
7429
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007430 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007431 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007432 curproxy->req_cap_pool = create_pool("ptrcap",
7433 curproxy->nb_req_cap * sizeof(char *),
7434 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007435 }
7436
7437 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007438 curproxy->rsp_cap_pool = create_pool("ptrcap",
7439 curproxy->nb_rsp_cap * sizeof(char *),
7440 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007441 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007442
Willy Tarreaubaaee002006-06-26 02:48:02 +02007443 /* first, we will invert the servers list order */
7444 newsrv = NULL;
7445 while (curproxy->srv) {
7446 struct server *next;
7447
7448 next = curproxy->srv->next;
7449 curproxy->srv->next = newsrv;
7450 newsrv = curproxy->srv;
7451 if (!next)
7452 break;
7453 curproxy->srv = next;
7454 }
7455
Willy Tarreau17edc812014-01-03 12:14:34 +01007456 /* Check that no server name conflicts. This causes trouble in the stats.
7457 * We only emit a warning for the first conflict affecting each server,
7458 * in order to avoid combinatory explosion if all servers have the same
7459 * name. We do that only for servers which do not have an explicit ID,
7460 * because these IDs were made also for distinguishing them and we don't
7461 * want to annoy people who correctly manage them.
7462 */
7463 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7464 struct server *other_srv;
7465
7466 if (newsrv->puid)
7467 continue;
7468
7469 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7470 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7471 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7472 newsrv->conf.file, newsrv->conf.line,
7473 proxy_type_str(curproxy), curproxy->id,
7474 newsrv->id, other_srv->conf.line);
7475 break;
7476 }
7477 }
7478 }
7479
Willy Tarreaudd701652010-05-25 23:03:02 +02007480 /* assign automatic UIDs to servers which don't have one yet */
7481 next_id = 1;
7482 newsrv = curproxy->srv;
7483 while (newsrv != NULL) {
7484 if (!newsrv->puid) {
7485 /* server ID not set, use automatic numbering with first
7486 * spare entry starting with next_svid.
7487 */
7488 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7489 newsrv->conf.id.key = newsrv->puid = next_id;
7490 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7491 }
7492 next_id++;
7493 newsrv = newsrv->next;
7494 }
7495
Willy Tarreau20697042007-11-15 23:26:18 +01007496 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007497 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007498
Willy Tarreau62c3be22012-01-20 13:12:32 +01007499 /*
7500 * If this server supports a maxconn parameter, it needs a dedicated
7501 * tasks to fill the emptied slots when a connection leaves.
7502 * Also, resolve deferred tracking dependency if needed.
7503 */
7504 newsrv = curproxy->srv;
7505 while (newsrv != NULL) {
7506 if (newsrv->minconn > newsrv->maxconn) {
7507 /* Only 'minconn' was specified, or it was higher than or equal
7508 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7509 * this will avoid further useless expensive computations.
7510 */
7511 newsrv->maxconn = newsrv->minconn;
7512 } else if (newsrv->maxconn && !newsrv->minconn) {
7513 /* minconn was not specified, so we set it to maxconn */
7514 newsrv->minconn = newsrv->maxconn;
7515 }
7516
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007517#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007518 if (newsrv->use_ssl || newsrv->check.use_ssl)
7519 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007520#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007521
Willy Tarreau2f075e92013-12-03 11:11:34 +01007522 /* set the check type on the server */
7523 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7524
Willy Tarreau62c3be22012-01-20 13:12:32 +01007525 if (newsrv->trackit) {
7526 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007527 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007528 char *pname, *sname;
7529
7530 pname = newsrv->trackit;
7531 sname = strrchr(pname, '/');
7532
7533 if (sname)
7534 *sname++ = '\0';
7535 else {
7536 sname = pname;
7537 pname = NULL;
7538 }
7539
7540 if (pname) {
7541 px = findproxy(pname, PR_CAP_BE);
7542 if (!px) {
7543 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7544 proxy_type_str(curproxy), curproxy->id,
7545 newsrv->id, pname);
7546 cfgerr++;
7547 goto next_srv;
7548 }
7549 } else
7550 px = curproxy;
7551
7552 srv = findserver(px, sname);
7553 if (!srv) {
7554 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7555 proxy_type_str(curproxy), curproxy->id,
7556 newsrv->id, sname);
7557 cfgerr++;
7558 goto next_srv;
7559 }
7560
Willy Tarreau32091232014-05-16 13:52:00 +02007561 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7562 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7563 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007564 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007565 "tracking as it does not have any check nor agent enabled.\n",
7566 proxy_type_str(curproxy), curproxy->id,
7567 newsrv->id, px->id, srv->id);
7568 cfgerr++;
7569 goto next_srv;
7570 }
7571
7572 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7573
7574 if (loop) {
7575 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7576 "belongs to a tracking chain looping back to %s/%s.\n",
7577 proxy_type_str(curproxy), curproxy->id,
7578 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007579 cfgerr++;
7580 goto next_srv;
7581 }
7582
7583 if (curproxy != px &&
7584 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7585 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7586 "tracking: disable-on-404 option inconsistency.\n",
7587 proxy_type_str(curproxy), curproxy->id,
7588 newsrv->id, px->id, srv->id);
7589 cfgerr++;
7590 goto next_srv;
7591 }
7592
7593 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007594 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007595 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007596 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007597 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007598 }
7599
7600 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007601 newsrv->tracknext = srv->trackers;
7602 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007603
7604 free(newsrv->trackit);
7605 newsrv->trackit = NULL;
7606 }
7607 next_srv:
7608 newsrv = newsrv->next;
7609 }
7610
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007611 /* We have to initialize the server lookup mechanism depending
7612 * on what LB algorithm was choosen.
7613 */
7614
7615 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7616 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7617 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007618 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7619 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7620 init_server_map(curproxy);
7621 } else {
7622 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7623 fwrr_init_server_groups(curproxy);
7624 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007625 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007626
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007627 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007628 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7629 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7630 fwlc_init_server_tree(curproxy);
7631 } else {
7632 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7633 fas_init_server_tree(curproxy);
7634 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007635 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007636
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007637 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007638 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7639 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7640 chash_init_server_tree(curproxy);
7641 } else {
7642 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7643 init_server_map(curproxy);
7644 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007645 break;
7646 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007647
7648 if (curproxy->options & PR_O_LOGASAP)
7649 curproxy->to_log &= ~LW_BYTES;
7650
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007651 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007652 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007653 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7654 proxy_type_str(curproxy), curproxy->id);
7655 err_code |= ERR_WARN;
7656 }
7657
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007658 if (curproxy->mode != PR_MODE_HTTP) {
7659 int optnum;
7660
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007661 if (curproxy->uri_auth) {
7662 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7663 proxy_type_str(curproxy), curproxy->id);
7664 err_code |= ERR_WARN;
7665 curproxy->uri_auth = NULL;
7666 }
7667
Willy Tarreau87cf5142011-08-19 22:57:24 +02007668 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007669 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7670 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7671 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007672 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007673 }
7674
7675 if (curproxy->options & PR_O_ORGTO) {
7676 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7677 "originalto", proxy_type_str(curproxy), curproxy->id);
7678 err_code |= ERR_WARN;
7679 curproxy->options &= ~PR_O_ORGTO;
7680 }
7681
7682 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7683 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7684 (curproxy->cap & cfg_opts[optnum].cap) &&
7685 (curproxy->options & cfg_opts[optnum].val)) {
7686 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7687 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7688 err_code |= ERR_WARN;
7689 curproxy->options &= ~cfg_opts[optnum].val;
7690 }
7691 }
7692
7693 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7694 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7695 (curproxy->cap & cfg_opts2[optnum].cap) &&
7696 (curproxy->options2 & cfg_opts2[optnum].val)) {
7697 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7698 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7699 err_code |= ERR_WARN;
7700 curproxy->options2 &= ~cfg_opts2[optnum].val;
7701 }
7702 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007703
Pieter Baauwd551fb52013-05-08 22:49:23 +02007704#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007705 if (curproxy->conn_src.bind_hdr_occ) {
7706 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007707 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007708 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007709 err_code |= ERR_WARN;
7710 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007711#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007712 }
7713
Willy Tarreaubaaee002006-06-26 02:48:02 +02007714 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007715 * ensure that we're not cross-dressing a TCP server into HTTP.
7716 */
7717 newsrv = curproxy->srv;
7718 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007719 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007720 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7721 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007722 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007723 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007724
Willy Tarreau0cec3312011-10-31 13:49:26 +01007725 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7726 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7727 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7728 err_code |= ERR_WARN;
7729 }
7730
Willy Tarreauc93cd162014-05-13 15:54:22 +02007731 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007732 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7733 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7734 err_code |= ERR_WARN;
7735 }
7736
Pieter Baauwd551fb52013-05-08 22:49:23 +02007737#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007738 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7739 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007740 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 +01007741 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007742 err_code |= ERR_WARN;
7743 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007744#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007745 newsrv = newsrv->next;
7746 }
7747
Willy Tarreaue42bd962014-09-16 16:21:19 +02007748 /* check if we have a frontend with "tcp-request content" looking at L7
7749 * with no inspect-delay
7750 */
7751 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7752 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7753 if (trule->action == TCP_ACT_CAPTURE &&
7754 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7755 break;
7756 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7757 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7758 break;
7759 }
7760
7761 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7762 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7763 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7764 " This means that these rules will randomly find their contents. This can be fixed by"
7765 " setting the tcp-request inspect-delay.\n",
7766 proxy_type_str(curproxy), curproxy->id);
7767 err_code |= ERR_WARN;
7768 }
7769 }
7770
Willy Tarreauc1a21672009-08-16 22:37:44 +02007771 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007772 if (!curproxy->accept)
7773 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007774
Willy Tarreauc1a21672009-08-16 22:37:44 +02007775 if (curproxy->tcp_req.inspect_delay ||
7776 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007777 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007778
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007779 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007780 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007781 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007782 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007783
7784 /* both TCP and HTTP must check switching rules */
7785 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7786 }
7787
7788 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007789 if (curproxy->tcp_req.inspect_delay ||
7790 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7791 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7792
Emeric Brun97679e72010-09-23 17:56:44 +02007793 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7794 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7795
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007796 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007797 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007798 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007799 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007800
7801 /* If the backend does requires RDP cookie persistence, we have to
7802 * enable the corresponding analyser.
7803 */
7804 if (curproxy->options2 & PR_O2_RDPC_PRST)
7805 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7806 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007807 }
7808
7809 /***********************************************************/
7810 /* At this point, target names have already been resolved. */
7811 /***********************************************************/
7812
7813 /* Check multi-process mode compatibility */
7814
7815 if (global.nbproc > 1 && global.stats_fe) {
7816 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7817 unsigned long mask;
7818
7819 mask = nbits(global.nbproc);
7820 if (global.stats_fe->bind_proc)
7821 mask &= global.stats_fe->bind_proc;
7822
7823 if (bind_conf->bind_proc)
7824 mask &= bind_conf->bind_proc;
7825
7826 /* stop here if more than one process is used */
7827 if (popcount(mask) > 1)
7828 break;
7829 }
7830 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7831 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");
7832 }
7833 }
7834
7835 /* Make each frontend inherit bind-process from its listeners when not specified. */
7836 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7837 if (curproxy->bind_proc)
7838 continue;
7839
7840 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7841 unsigned long mask;
7842
Willy Tarreaue428b082015-05-04 21:57:58 +02007843 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007844 curproxy->bind_proc |= mask;
7845 }
7846
7847 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02007848 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007849 }
7850
7851 if (global.stats_fe) {
7852 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7853 unsigned long mask;
7854
Willy Tarreaue428b082015-05-04 21:57:58 +02007855 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007856 global.stats_fe->bind_proc |= mask;
7857 }
7858 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02007859 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007860 }
7861
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007862 /* propagate bindings from frontends to backends. Don't do it if there
7863 * are any fatal errors as we must not call it with unresolved proxies.
7864 */
7865 if (!cfgerr) {
7866 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7867 if (curproxy->cap & PR_CAP_FE)
7868 propagate_processes(curproxy, NULL);
7869 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007870 }
7871
7872 /* Bind each unbound backend to all processes when not specified. */
7873 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7874 if (curproxy->bind_proc)
7875 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02007876 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02007877 }
7878
7879 /*******************************************************/
7880 /* At this step, all proxies have a non-null bind_proc */
7881 /*******************************************************/
7882
7883 /* perform the final checks before creating tasks */
7884
7885 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7886 struct listener *listener;
7887 unsigned int next_id;
7888 int nbproc;
7889
7890 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007891
Emeric Brunc52962f2012-11-15 18:28:02 +01007892#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007893 /* Configure SSL for each bind line.
7894 * Note: if configuration fails at some point, the ->ctx member
7895 * remains NULL so that listeners can later detach.
7896 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007897 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007898 int alloc_ctx;
7899
Emeric Brunc52962f2012-11-15 18:28:02 +01007900 if (!bind_conf->is_ssl) {
7901 if (bind_conf->default_ctx) {
7902 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7903 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7904 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007905 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007906 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007907 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007908 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007909 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007910 cfgerr++;
7911 continue;
7912 }
7913
Emeric Brun8dc60392014-05-09 13:52:00 +02007914 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007915 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007916 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7917 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");
7918 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007919 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007920 cfgerr++;
7921 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007922 }
7923
Emeric Brunfc0421f2012-09-07 17:30:07 +02007924 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007925 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007926 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007927#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007928
Willy Tarreaue6b98942007-10-29 01:09:36 +01007929 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007930 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007931 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007932 if (!listener->luid) {
7933 /* listener ID not set, use automatic numbering with first
7934 * spare entry starting with next_luid.
7935 */
7936 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7937 listener->conf.id.key = listener->luid = next_id;
7938 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007939 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007940 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007941
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007942 /* enable separate counters */
7943 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7944 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007945 if (!listener->name)
7946 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007947 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007948
Willy Tarreaue6b98942007-10-29 01:09:36 +01007949 if (curproxy->options & PR_O_TCP_NOLING)
7950 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007951 if (!listener->maxconn)
7952 listener->maxconn = curproxy->maxconn;
7953 if (!listener->backlog)
7954 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007955 if (!listener->maxaccept)
7956 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7957
7958 /* we want to have an optimal behaviour on single process mode to
7959 * maximize the work at once, but in multi-process we want to keep
7960 * some fairness between processes, so we target half of the max
7961 * number of events to be balanced over all the processes the proxy
7962 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7963 * used to disable the limit.
7964 */
7965 if (listener->maxaccept > 0) {
7966 if (nbproc > 1)
7967 listener->maxaccept = (listener->maxaccept + 1) / 2;
7968 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7969 }
7970
Willy Tarreau9903f0e2015-04-04 18:50:31 +02007971 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02007972 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007973 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01007974 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007975
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007976 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7977 listener->options |= LI_O_TCP_RULES;
7978
Willy Tarreaude3041d2010-05-31 10:56:17 +02007979 if (curproxy->mon_mask.s_addr)
7980 listener->options |= LI_O_CHK_MONNET;
7981
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007982 /* smart accept mode is automatic in HTTP mode */
7983 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007984 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007985 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7986 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007987 }
7988
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007989 /* Release unused SSL configs */
7990 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7991 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007992 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007993#ifdef USE_OPENSSL
7994 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007995 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007996 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007997 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007998 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007999 if(bind_conf->keys_ref) {
8000 free(bind_conf->keys_ref->filename);
8001 free(bind_conf->keys_ref->tlskeys);
8002 free(bind_conf->keys_ref);
8003 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008004#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008005 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008006
Willy Tarreau102df612014-05-07 23:56:38 +02008007 if (nbproc > 1) {
8008 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008009 int count, maxproc = 0;
8010
8011 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8012 count = popcount(bind_conf->bind_proc);
8013 if (count > maxproc)
8014 maxproc = count;
8015 }
8016 /* backends have 0, frontends have 1 or more */
8017 if (maxproc != 1)
8018 Warning("Proxy '%s': in multi-process mode, stats will be"
8019 " limited to process assigned to the current request.\n",
8020 curproxy->id);
8021
Willy Tarreau102df612014-05-07 23:56:38 +02008022 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8023 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8024 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008025 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008026 }
Willy Tarreau102df612014-05-07 23:56:38 +02008027 if (curproxy->appsession_name) {
8028 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
8029 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008030 }
Willy Tarreau102df612014-05-07 23:56:38 +02008031 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8032 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8033 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008034 }
8035 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008036
8037 /* create the task associated with the proxy */
8038 curproxy->task = task_new();
8039 if (curproxy->task) {
8040 curproxy->task->context = curproxy;
8041 curproxy->task->process = manage_proxy;
8042 /* no need to queue, it will be done automatically if some
8043 * listener gets limited.
8044 */
8045 curproxy->task->expire = TICK_ETERNITY;
8046 } else {
8047 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8048 curproxy->id);
8049 cfgerr++;
8050 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008051 }
8052
Willy Tarreaufbb78422011-06-05 15:38:35 +02008053 /* automatically compute fullconn if not set. We must not do it in the
8054 * loop above because cross-references are not yet fully resolved.
8055 */
8056 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8057 /* If <fullconn> is not set, let's set it to 10% of the sum of
8058 * the possible incoming frontend's maxconns.
8059 */
8060 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8061 struct proxy *fe;
8062 int total = 0;
8063
8064 /* sum up the number of maxconns of frontends which
8065 * reference this backend at least once or which are
8066 * the same one ('listen').
8067 */
8068 for (fe = proxy; fe; fe = fe->next) {
8069 struct switching_rule *rule;
8070 struct hdr_exp *exp;
8071 int found = 0;
8072
8073 if (!(fe->cap & PR_CAP_FE))
8074 continue;
8075
8076 if (fe == curproxy) /* we're on a "listen" instance */
8077 found = 1;
8078
8079 if (fe->defbe.be == curproxy) /* "default_backend" */
8080 found = 1;
8081
8082 /* check if a "use_backend" rule matches */
8083 if (!found) {
8084 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008085 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008086 found = 1;
8087 break;
8088 }
8089 }
8090 }
8091
8092 /* check if a "reqsetbe" rule matches */
8093 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
8094 if (exp->action == ACT_SETBE &&
8095 (struct proxy *)exp->replace == curproxy) {
8096 found = 1;
8097 break;
8098 }
8099 }
8100
8101 /* now we've checked all possible ways to reference a backend
8102 * from a frontend.
8103 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008104 if (!found)
8105 continue;
8106 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008107 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008108 /* we have the sum of the maxconns in <total>. We only
8109 * keep 10% of that sum to set the default fullconn, with
8110 * a hard minimum of 1 (to avoid a divide by zero).
8111 */
8112 curproxy->fullconn = (total + 9) / 10;
8113 if (!curproxy->fullconn)
8114 curproxy->fullconn = 1;
8115 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008116 }
8117
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008118 /*
8119 * Recount currently required checks.
8120 */
8121
8122 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8123 int optnum;
8124
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008125 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8126 if (curproxy->options & cfg_opts[optnum].val)
8127 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008128
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008129 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8130 if (curproxy->options2 & cfg_opts2[optnum].val)
8131 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008132 }
8133
Willy Tarreau0fca4832015-05-01 19:12:05 +02008134 /* compute the required process bindings for the peers */
8135 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8136 if (curproxy->table.peers.p)
8137 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8138
Willy Tarreau122541c2011-09-07 21:24:49 +02008139 if (peers) {
8140 struct peers *curpeers = peers, **last;
8141 struct peer *p, *pb;
8142
Willy Tarreau1e273012015-05-01 19:15:17 +02008143 /* Remove all peers sections which don't have a valid listener,
8144 * which are not used by any table, or which are bound to more
8145 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008146 */
8147 last = &peers;
8148 while (*last) {
8149 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008150
8151 if (curpeers->state == PR_STSTOPPED) {
8152 /* the "disabled" keyword was present */
8153 if (curpeers->peers_fe)
8154 stop_proxy(curpeers->peers_fe);
8155 curpeers->peers_fe = NULL;
8156 }
8157 else if (!curpeers->peers_fe) {
8158 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8159 curpeers->id, localpeer);
8160 }
Willy Tarreau1e273012015-05-01 19:15:17 +02008161 else if (popcount(curpeers->peers_fe->bind_proc) != 1) {
8162 /* either it's totally stopped or too much used */
8163 if (curpeers->peers_fe->bind_proc) {
8164 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008165 "running in different processes (%d different ones). "
8166 "Check global.nbproc and all tables' bind-process "
8167 "settings.\n", curpeers->id, popcount(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008168 cfgerr++;
8169 }
8170 stop_proxy(curpeers->peers_fe);
8171 curpeers->peers_fe = NULL;
8172 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008173 else {
Willy Tarreau122541c2011-09-07 21:24:49 +02008174 last = &curpeers->next;
8175 continue;
8176 }
8177
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008178 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008179 p = curpeers->remote;
8180 while (p) {
8181 pb = p->next;
8182 free(p->id);
8183 free(p);
8184 p = pb;
8185 }
8186
8187 /* Destroy and unlink this curpeers section.
8188 * Note: curpeers is backed up into *last.
8189 */
8190 free(curpeers->id);
8191 curpeers = curpeers->next;
8192 free(*last);
8193 *last = curpeers;
8194 }
8195 }
8196
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008197 /* initialize stick-tables on backend capable proxies. This must not
8198 * be done earlier because the data size may be discovered while parsing
8199 * other proxies.
8200 */
8201 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8202 if (curproxy->state == PR_STSTOPPED)
8203 continue;
8204
8205 if (!stktable_init(&curproxy->table)) {
8206 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8207 cfgerr++;
8208 }
8209 }
8210
Simon Horman0d16a402015-01-30 11:22:58 +09008211 if (mailers) {
8212 struct mailers *curmailers = mailers, **last;
8213 struct mailer *m, *mb;
8214
8215 /* Remove all mailers sections which don't have a valid listener.
8216 * This can happen when a mailers section is never referenced.
8217 */
8218 last = &mailers;
8219 while (*last) {
8220 curmailers = *last;
8221 if (curmailers->users) {
8222 last = &curmailers->next;
8223 continue;
8224 }
8225
8226 Warning("Removing incomplete section 'mailers %s'.\n",
8227 curmailers->id);
8228
8229 m = curmailers->mailer_list;
8230 while (m) {
8231 mb = m->next;
8232 free(m->id);
8233 free(m);
8234 m = mb;
8235 }
8236
8237 /* Destroy and unlink this curmailers section.
8238 * Note: curmailers is backed up into *last.
8239 */
8240 free(curmailers->id);
8241 curmailers = curmailers->next;
8242 free(*last);
8243 *last = curmailers;
8244 }
8245 }
8246
Willy Tarreau34eb6712011-10-24 18:15:04 +02008247 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008248 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008249 MEM_F_SHARED);
8250
Willy Tarreaubb925012009-07-23 13:36:36 +02008251 if (cfgerr > 0)
8252 err_code |= ERR_ALERT | ERR_FATAL;
8253 out:
8254 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008255}
8256
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008257/*
8258 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8259 * parsing sessions.
8260 */
8261void cfg_register_keywords(struct cfg_kw_list *kwl)
8262{
8263 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8264}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008265
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008266/*
8267 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8268 */
8269void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8270{
8271 LIST_DEL(&kwl->list);
8272 LIST_INIT(&kwl->list);
8273}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008274
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008275/* this function register new section in the haproxy configuration file.
8276 * <section_name> is the name of this new section and <section_parser>
8277 * is the called parser. If two section declaration have the same name,
8278 * only the first declared is used.
8279 */
8280int cfg_register_section(char *section_name,
8281 int (*section_parser)(const char *, int, char **, int))
8282{
8283 struct cfg_section *cs;
8284
8285 cs = calloc(1, sizeof(*cs));
8286 if (!cs) {
8287 Alert("register section '%s': out of memory.\n", section_name);
8288 return 0;
8289 }
8290
8291 cs->section_name = section_name;
8292 cs->section_parser = section_parser;
8293
8294 LIST_ADDQ(&sections, &cs->list);
8295
8296 return 1;
8297}
8298
Willy Tarreaubaaee002006-06-26 02:48:02 +02008299/*
8300 * Local variables:
8301 * c-indent-level: 8
8302 * c-basic-offset: 8
8303 * End:
8304 */