blob: 45c9d6d31fc96714595cb5db85a1ce949ea03ad3 [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;
2109 else if (!strcmp(args[0], "backend"))
2110 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 Assmann69e273f2013-12-11 00:52:19 +01004686 if (strcmp(args[1], "connect") == 0) {
4687 const char *ptr_arg;
4688 int cur_arg;
4689 struct tcpcheck_rule *tcpcheck;
4690 struct list *l;
4691
4692 /* check if first rule is also a 'connect' action */
4693 l = (struct list *)&curproxy->tcpcheck_rules;
4694 if (l->p != l->n) {
4695 tcpcheck = (struct tcpcheck_rule *)l->n;
4696 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4697 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4698 file, linenum);
4699 err_code |= ERR_ALERT | ERR_FATAL;
4700 goto out;
4701 }
4702 }
4703
4704 cur_arg = 2;
4705 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4706 tcpcheck->action = TCPCHK_ACT_CONNECT;
4707
4708 /* parsing each parameters to fill up the rule */
4709 while (*(ptr_arg = args[cur_arg])) {
4710 /* tcp port */
4711 if (strcmp(args[cur_arg], "port") == 0) {
4712 if ( (atol(args[cur_arg + 1]) > 65535) ||
4713 (atol(args[cur_arg + 1]) < 1) ){
4714 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4715 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4716 err_code |= ERR_ALERT | ERR_FATAL;
4717 goto out;
4718 }
4719 tcpcheck->port = atol(args[cur_arg + 1]);
4720 cur_arg += 2;
4721 }
4722 /* send proxy protocol */
4723 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4724 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4725 cur_arg++;
4726 }
4727#ifdef USE_OPENSSL
4728 else if (strcmp(args[cur_arg], "ssl") == 0) {
4729 curproxy->options |= PR_O_TCPCHK_SSL;
4730 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4731 cur_arg++;
4732 }
4733#endif /* USE_OPENSSL */
4734 else {
4735#ifdef USE_OPENSSL
4736 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4737#else /* USE_OPENSSL */
4738 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4739#endif /* USE_OPENSSL */
4740 file, linenum, args[0], args[1], args[cur_arg]);
4741 err_code |= ERR_ALERT | ERR_FATAL;
4742 goto out;
4743 }
4744
4745 }
4746
4747 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4748 }
4749 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004750 if (! *(args[2]) ) {
4751 /* SEND string expected */
4752 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4753 file, linenum, args[0], args[1], args[2]);
4754 err_code |= ERR_ALERT | ERR_FATAL;
4755 goto out;
4756 } else {
4757 struct tcpcheck_rule *tcpcheck;
4758
4759 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4760
4761 tcpcheck->action = TCPCHK_ACT_SEND;
4762 tcpcheck->string_len = strlen(args[2]);
4763 tcpcheck->string = strdup(args[2]);
4764 tcpcheck->expect_regex = NULL;
4765
4766 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4767 }
4768 }
4769 else if (strcmp(args[1], "send-binary") == 0) {
4770 if (! *(args[2]) ) {
4771 /* SEND binary string expected */
4772 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4773 file, linenum, args[0], args[1], args[2]);
4774 err_code |= ERR_ALERT | ERR_FATAL;
4775 goto out;
4776 } else {
4777 struct tcpcheck_rule *tcpcheck;
4778 char *err = NULL;
4779
4780 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4781
4782 tcpcheck->action = TCPCHK_ACT_SEND;
4783 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4784 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4785 file, linenum, args[0], args[1], args[2], err);
4786 err_code |= ERR_ALERT | ERR_FATAL;
4787 goto out;
4788 }
4789 tcpcheck->expect_regex = NULL;
4790
4791 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4792 }
4793 }
4794 else if (strcmp(args[1], "expect") == 0) {
4795 const char *ptr_arg;
4796 int cur_arg;
4797 int inverse = 0;
4798
4799 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4800 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4801 err_code |= ERR_ALERT | ERR_FATAL;
4802 goto out;
4803 }
4804
4805 cur_arg = 2;
4806 /* consider exclamation marks, sole or at the beginning of a word */
4807 while (*(ptr_arg = args[cur_arg])) {
4808 while (*ptr_arg == '!') {
4809 inverse = !inverse;
4810 ptr_arg++;
4811 }
4812 if (*ptr_arg)
4813 break;
4814 cur_arg++;
4815 }
4816 /* now ptr_arg points to the beginning of a word past any possible
4817 * exclamation mark, and cur_arg is the argument which holds this word.
4818 */
4819 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004820 struct tcpcheck_rule *tcpcheck;
4821 char *err = NULL;
4822
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004823 if (!*(args[cur_arg + 1])) {
4824 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4825 file, linenum, args[0], args[1], ptr_arg);
4826 err_code |= ERR_ALERT | ERR_FATAL;
4827 goto out;
4828 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004829
4830 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4831
4832 tcpcheck->action = TCPCHK_ACT_EXPECT;
4833 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4834 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4835 file, linenum, args[0], args[1], args[2], err);
4836 err_code |= ERR_ALERT | ERR_FATAL;
4837 goto out;
4838 }
4839 tcpcheck->expect_regex = NULL;
4840 tcpcheck->inverse = inverse;
4841
4842 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4843 }
4844 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004845 struct tcpcheck_rule *tcpcheck;
4846
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004847 if (!*(args[cur_arg + 1])) {
4848 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4849 file, linenum, args[0], args[1], ptr_arg);
4850 err_code |= ERR_ALERT | ERR_FATAL;
4851 goto out;
4852 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004853
4854 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4855
4856 tcpcheck->action = TCPCHK_ACT_EXPECT;
4857 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4858 tcpcheck->string = strdup(args[cur_arg + 1]);
4859 tcpcheck->expect_regex = NULL;
4860 tcpcheck->inverse = inverse;
4861
4862 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4863 }
4864 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004865 struct tcpcheck_rule *tcpcheck;
4866
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004867 if (!*(args[cur_arg + 1])) {
4868 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4869 file, linenum, args[0], args[1], ptr_arg);
4870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
4872 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004873
4874 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4875
4876 tcpcheck->action = TCPCHK_ACT_EXPECT;
4877 tcpcheck->string_len = 0;
4878 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004879 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4880 error = NULL;
4881 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4882 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4883 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4884 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004885 err_code |= ERR_ALERT | ERR_FATAL;
4886 goto out;
4887 }
4888 tcpcheck->inverse = inverse;
4889
4890 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4891 }
4892 else {
4893 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4894 file, linenum, args[0], args[1], ptr_arg);
4895 err_code |= ERR_ALERT | ERR_FATAL;
4896 goto out;
4897 }
4898 }
4899 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004900 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004901 err_code |= ERR_ALERT | ERR_FATAL;
4902 goto out;
4903 }
4904 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004905 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004906 if (curproxy == &defproxy) {
4907 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004908 err_code |= ERR_ALERT | ERR_FATAL;
4909 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004910 }
4911
Willy Tarreaub80c2302007-11-30 20:51:32 +01004912 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004913 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004914
4915 if (strcmp(args[1], "fail") == 0) {
4916 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004917 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004918 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4919 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004920 err_code |= ERR_ALERT | ERR_FATAL;
4921 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004922 }
4923
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004924 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4925 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4926 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004927 err_code |= ERR_ALERT | ERR_FATAL;
4928 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004929 }
4930 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4931 }
4932 else {
4933 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004934 err_code |= ERR_ALERT | ERR_FATAL;
4935 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004936 }
4937 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004938#ifdef TPROXY
4939 else if (!strcmp(args[0], "transparent")) {
4940 /* enable transparent proxy connections */
4941 curproxy->options |= PR_O_TRANSP;
4942 }
4943#endif
4944 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004945 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004946 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004947
Willy Tarreaubaaee002006-06-26 02:48:02 +02004948 if (*(args[1]) == 0) {
4949 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004950 err_code |= ERR_ALERT | ERR_FATAL;
4951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 }
4953 curproxy->maxconn = atol(args[1]);
4954 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004955 else if (!strcmp(args[0], "backlog")) { /* backlog */
4956 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004957 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004958
4959 if (*(args[1]) == 0) {
4960 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004961 err_code |= ERR_ALERT | ERR_FATAL;
4962 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004963 }
4964 curproxy->backlog = atol(args[1]);
4965 }
Willy Tarreau86034312006-12-29 00:10:33 +01004966 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004967 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004968 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004969
Willy Tarreau86034312006-12-29 00:10:33 +01004970 if (*(args[1]) == 0) {
4971 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004972 err_code |= ERR_ALERT | ERR_FATAL;
4973 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004974 }
4975 curproxy->fullconn = atol(args[1]);
4976 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004977 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4978 if (*(args[1]) == 0) {
4979 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004980 err_code |= ERR_ALERT | ERR_FATAL;
4981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004982 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004983 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4984 if (err) {
4985 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4986 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004987 err_code |= ERR_ALERT | ERR_FATAL;
4988 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004989 }
4990 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004991 }
4992 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004993 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004994 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004995 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004996
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997 if (curproxy == &defproxy) {
4998 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004999 err_code |= ERR_ALERT | ERR_FATAL;
5000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005001 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005002 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005003 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005004
Willy Tarreau902636f2013-03-10 19:44:48 +01005005 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005006 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005007 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005008 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005009 goto out;
5010 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005011
5012 proto = protocol_by_family(sk->ss_family);
5013 if (!proto || !proto->connect) {
5014 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5015 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005016 err_code |= ERR_ALERT | ERR_FATAL;
5017 goto out;
5018 }
5019
5020 if (port1 != port2) {
5021 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5022 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005023 err_code |= ERR_ALERT | ERR_FATAL;
5024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005026
5027 if (!port1) {
5028 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5029 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005030 err_code |= ERR_ALERT | ERR_FATAL;
5031 goto out;
5032 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005033
Willy Tarreaud5191e72010-02-09 20:50:45 +01005034 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005035 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005036 }
5037 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005038 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005039 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005040
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005041 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5042 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005046 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005047 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005048 /**
5049 * The syntax for hash-type config element is
5050 * hash-type {map-based|consistent} [[<algo>] avalanche]
5051 *
5052 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5053 */
5054 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005055
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005056 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5057 err_code |= ERR_WARN;
5058
5059 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005060 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5061 }
5062 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005063 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5064 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005065 else if (strcmp(args[1], "avalanche") == 0) {
5066 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]);
5067 err_code |= ERR_ALERT | ERR_FATAL;
5068 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005069 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005070 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005071 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005072 err_code |= ERR_ALERT | ERR_FATAL;
5073 goto out;
5074 }
Bhaskar98634f02013-10-29 23:30:51 -04005075
5076 /* set the hash function to use */
5077 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005078 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005079 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005080
5081 /* if consistent with no argument, then avalanche modifier is also applied */
5082 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5083 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005084 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005085 /* set the hash function */
5086 if (!strcmp(args[2], "sdbm")) {
5087 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5088 }
5089 else if (!strcmp(args[2], "djb2")) {
5090 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005091 }
5092 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005093 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005094 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005095 else if (!strcmp(args[2], "crc32")) {
5096 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5097 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005098 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005099 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 -05005100 err_code |= ERR_ALERT | ERR_FATAL;
5101 goto out;
5102 }
5103
5104 /* set the hash modifier */
5105 if (!strcmp(args[3], "avalanche")) {
5106 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5107 }
5108 else if (*args[3]) {
5109 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5110 err_code |= ERR_ALERT | ERR_FATAL;
5111 goto out;
5112 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005113 }
William Lallemanda73203e2012-03-12 12:48:57 +01005114 }
William Lallemanda73203e2012-03-12 12:48:57 +01005115 else if (strcmp(args[0], "unique-id-format") == 0) {
5116 if (!*(args[1])) {
5117 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5118 err_code |= ERR_ALERT | ERR_FATAL;
5119 goto out;
5120 }
William Lallemand3203ff42012-11-11 17:30:56 +01005121 if (*(args[2])) {
5122 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5123 err_code |= ERR_ALERT | ERR_FATAL;
5124 goto out;
5125 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005126 free(curproxy->conf.uniqueid_format_string);
5127 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005128
Willy Tarreau62a61232013-04-12 18:13:46 +02005129 free(curproxy->conf.uif_file);
5130 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5131 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005132 }
William Lallemanda73203e2012-03-12 12:48:57 +01005133
5134 else if (strcmp(args[0], "unique-id-header") == 0) {
5135 if (!*(args[1])) {
5136 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5137 err_code |= ERR_ALERT | ERR_FATAL;
5138 goto out;
5139 }
5140 free(curproxy->header_unique_id);
5141 curproxy->header_unique_id = strdup(args[1]);
5142 }
5143
William Lallemand723b73a2012-02-08 16:37:49 +01005144 else if (strcmp(args[0], "log-format") == 0) {
5145 if (!*(args[1])) {
5146 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5147 err_code |= ERR_ALERT | ERR_FATAL;
5148 goto out;
5149 }
William Lallemand3203ff42012-11-11 17:30:56 +01005150 if (*(args[2])) {
5151 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5152 err_code |= ERR_ALERT | ERR_FATAL;
5153 goto out;
5154 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005155
Willy Tarreau62a61232013-04-12 18:13:46 +02005156 if (curproxy->conf.logformat_string != default_http_log_format &&
5157 curproxy->conf.logformat_string != default_tcp_log_format &&
5158 curproxy->conf.logformat_string != clf_http_log_format)
5159 free(curproxy->conf.logformat_string);
5160 curproxy->conf.logformat_string = strdup(args[1]);
5161
5162 free(curproxy->conf.lfs_file);
5163 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5164 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005165
5166 /* get a chance to improve log-format error reporting by
5167 * reporting the correct line-number when possible.
5168 */
5169 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5170 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5171 file, linenum, curproxy->id);
5172 err_code |= ERR_WARN;
5173 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005174 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005175 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5176 if (*(args[1]) == 0) {
5177 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5178 err_code |= ERR_ALERT | ERR_FATAL;
5179 goto out;
5180 }
5181 free(curproxy->log_tag);
5182 curproxy->log_tag = strdup(args[1]);
5183 }
William Lallemand0f99e342011-10-12 17:50:54 +02005184 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5185 /* delete previous herited or defined syslog servers */
5186 struct logsrv *back;
5187
5188 if (*(args[1]) != 0) {
5189 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5190 err_code |= ERR_ALERT | ERR_FATAL;
5191 goto out;
5192 }
5193
William Lallemand723b73a2012-02-08 16:37:49 +01005194 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5195 LIST_DEL(&tmplogsrv->list);
5196 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005197 }
5198 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005200 struct logsrv *logsrv;
5201
Willy Tarreaubaaee002006-06-26 02:48:02 +02005202 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005203 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005204 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005205 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005206 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005207 LIST_INIT(&node->list);
5208 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5209 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 }
5211 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005212 struct sockaddr_storage *sk;
5213 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005214 int arg = 0;
5215 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005216
5217 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005218
Willy Tarreau18324f52014-06-27 18:10:07 +02005219 /* just after the address, a length may be specified */
5220 if (strcmp(args[arg+2], "len") == 0) {
5221 len = atoi(args[arg+3]);
5222 if (len < 80 || len > 65535) {
5223 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5224 file, linenum, args[arg+3]);
5225 err_code |= ERR_ALERT | ERR_FATAL;
5226 goto out;
5227 }
5228 logsrv->maxlen = len;
5229
5230 /* skip these two args */
5231 arg += 2;
5232 }
5233 else
5234 logsrv->maxlen = MAX_SYSLOG_LEN;
5235
5236 if (logsrv->maxlen > global.max_syslog_len) {
5237 global.max_syslog_len = logsrv->maxlen;
5238 logline = realloc(logline, global.max_syslog_len + 1);
5239 }
5240
5241 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005242 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005243 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005244 err_code |= ERR_ALERT | ERR_FATAL;
5245 goto out;
5246
Willy Tarreaubaaee002006-06-26 02:48:02 +02005247 }
5248
William Lallemand0f99e342011-10-12 17:50:54 +02005249 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005250 if (*(args[arg+3])) {
5251 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005252 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005253 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005254 err_code |= ERR_ALERT | ERR_FATAL;
5255 goto out;
5256
Willy Tarreaubaaee002006-06-26 02:48:02 +02005257 }
5258 }
5259
William Lallemand0f99e342011-10-12 17:50:54 +02005260 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005261 if (*(args[arg+4])) {
5262 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005263 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005264 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005265 err_code |= ERR_ALERT | ERR_FATAL;
5266 goto out;
5267
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005268 }
5269 }
5270
Willy Tarreau902636f2013-03-10 19:44:48 +01005271 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005272 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005273 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005274 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005275 goto out;
5276 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005277
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005278 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005279
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005280 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005281 if (port1 != port2) {
5282 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5283 file, linenum, args[0], args[1]);
5284 err_code |= ERR_ALERT | ERR_FATAL;
5285 goto out;
5286 }
5287
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005288 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005289 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005290 }
William Lallemand0f99e342011-10-12 17:50:54 +02005291
5292 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005293 }
5294 else {
5295 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5296 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005297 err_code |= ERR_ALERT | ERR_FATAL;
5298 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299 }
5300 }
5301 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005302 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005303 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005304 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005305 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005306
Willy Tarreau977b8e42006-12-29 14:19:17 +01005307 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005308 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005309
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005311 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5312 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005313 err_code |= ERR_ALERT | ERR_FATAL;
5314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005315 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005316
5317 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005318 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5319 free(curproxy->conn_src.iface_name);
5320 curproxy->conn_src.iface_name = NULL;
5321 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005322
Willy Tarreau902636f2013-03-10 19:44:48 +01005323 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005324 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005325 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005326 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005327 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005328 goto out;
5329 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005330
5331 proto = protocol_by_family(sk->ss_family);
5332 if (!proto || !proto->connect) {
5333 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005334 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005335 err_code |= ERR_ALERT | ERR_FATAL;
5336 goto out;
5337 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005338
5339 if (port1 != port2) {
5340 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5341 file, linenum, args[0], args[1]);
5342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
5344 }
5345
Willy Tarreauef9a3602012-12-08 22:29:20 +01005346 curproxy->conn_src.source_addr = *sk;
5347 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005348
5349 cur_arg = 2;
5350 while (*(args[cur_arg])) {
5351 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005352#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5353#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005354 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005355 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5356 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005357 err_code |= ERR_ALERT | ERR_FATAL;
5358 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005359 }
5360#endif
5361 if (!*args[cur_arg + 1]) {
5362 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5363 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005364 err_code |= ERR_ALERT | ERR_FATAL;
5365 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005366 }
5367
5368 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005369 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5370 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005371 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005372 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5373 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005374 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5375 char *name, *end;
5376
5377 name = args[cur_arg+1] + 7;
5378 while (isspace(*name))
5379 name++;
5380
5381 end = name;
5382 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5383 end++;
5384
Willy Tarreauef9a3602012-12-08 22:29:20 +01005385 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5386 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5387 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5388 curproxy->conn_src.bind_hdr_len = end - name;
5389 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5390 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5391 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005392
5393 /* now look for an occurrence number */
5394 while (isspace(*end))
5395 end++;
5396 if (*end == ',') {
5397 end++;
5398 name = end;
5399 if (*end == '-')
5400 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005401 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005402 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005403 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005404 }
5405
Willy Tarreauef9a3602012-12-08 22:29:20 +01005406 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005407 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5408 " occurrences values smaller than %d.\n",
5409 file, linenum, MAX_HDR_HISTORY);
5410 err_code |= ERR_ALERT | ERR_FATAL;
5411 goto out;
5412 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005413 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005414 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005415
Willy Tarreau902636f2013-03-10 19:44:48 +01005416 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005417 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005418 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005419 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005420 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005421 goto out;
5422 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005423
5424 proto = protocol_by_family(sk->ss_family);
5425 if (!proto || !proto->connect) {
5426 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5427 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005428 err_code |= ERR_ALERT | ERR_FATAL;
5429 goto out;
5430 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005431
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005432 if (port1 != port2) {
5433 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5434 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005435 err_code |= ERR_ALERT | ERR_FATAL;
5436 goto out;
5437 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005438 curproxy->conn_src.tproxy_addr = *sk;
5439 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005440 }
5441 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005442#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005443 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005444#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005445#else /* no TPROXY support */
5446 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005447 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005448 err_code |= ERR_ALERT | ERR_FATAL;
5449 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005450#endif
5451 cur_arg += 2;
5452 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005453 }
5454
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005455 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5456#ifdef SO_BINDTODEVICE
5457 if (!*args[cur_arg + 1]) {
5458 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5459 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005460 err_code |= ERR_ALERT | ERR_FATAL;
5461 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005462 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005463 free(curproxy->conn_src.iface_name);
5464 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5465 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005466 global.last_checks |= LSTCHK_NETADM;
5467#else
5468 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5469 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005470 err_code |= ERR_ALERT | ERR_FATAL;
5471 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005472#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005473 cur_arg += 2;
5474 continue;
5475 }
5476 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005477 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005478 err_code |= ERR_ALERT | ERR_FATAL;
5479 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005481 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005482 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5483 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5484 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005485 err_code |= ERR_ALERT | ERR_FATAL;
5486 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005487 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005488 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005489 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005490 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5491 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005492 err_code |= ERR_ALERT | ERR_FATAL;
5493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005494 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005495
5496 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005497 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005498 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005499 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005501 }
5502 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005503 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005504 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005505 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005506 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005507 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005508 }
5509 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005510 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005511 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005512 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005513 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005514 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005515 }
5516 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005517 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005518 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005519 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005520 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005522 }
5523 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005524 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005525 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005526 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005527 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005529 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005530 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005531 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005532 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005533 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005534 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005535 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005536 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005537 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005538 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005539 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005540 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005541 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005542 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005543
5544 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5545 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 +01005546 }
5547 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005548 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005549 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005550 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005551 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005552 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005553
5554 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5555 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 +01005556 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005557 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005558 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005559 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5560 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005561 err_code |= ERR_ALERT | ERR_FATAL;
5562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005563 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005564
5565 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005566 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005567 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005568 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005570 }
5571 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005572 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005573 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005574 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005575 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005577 }
5578 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005579 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005580 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005581 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005582 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005583 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005584 }
5585 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005586 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005587 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005588 args[0], args[1], NULL, (const char **)args+2);
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], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
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_ALLOW, REG_ICASE,
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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005599 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
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_TARPIT, REG_ICASE,
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 Tarreaub8750a82006-09-03 09:56:00 +02005605 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005606 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005607 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005608
Willy Tarreaubaaee002006-06-26 02:48:02 +02005609 if (curproxy == &defproxy) {
5610 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005611 err_code |= ERR_ALERT | ERR_FATAL;
5612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005613 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005614 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005615 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005616
Willy Tarreaubaaee002006-06-26 02:48:02 +02005617 if (*(args[1]) == 0) {
5618 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005619 err_code |= ERR_ALERT | ERR_FATAL;
5620 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005621 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005622
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005623 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005624 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5625 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5626 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005627 err_code |= ERR_ALERT | ERR_FATAL;
5628 goto out;
5629 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005630 err_code |= warnif_cond_conflicts(cond,
5631 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5632 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005633 }
5634 else if (*args[2]) {
5635 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5636 file, linenum, args[0], args[2]);
5637 err_code |= ERR_ALERT | ERR_FATAL;
5638 goto out;
5639 }
5640
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005641 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005642 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005643 wl->s = strdup(args[1]);
5644 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005645 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005646 }
5647 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
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 Tarreau977b8e42006-12-29 14:19:17 +01005654
Willy Tarreauade5ec42010-01-28 19:33:49 +01005655 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005656 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +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], "rspdel")) { /* delete response header from a regex */
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_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +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], "rspdeny")) { /* block response header from a regex */
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_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +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], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005676 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005677 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5678 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005679 err_code |= ERR_ALERT | ERR_FATAL;
5680 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005681 }
5682
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_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005685 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005686 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005688 }
5689 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a 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_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005692 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005693 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005694 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005695 }
5696 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005697 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005698 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005699 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005700 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005702 }
5703 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005704 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005705
Willy Tarreaubaaee002006-06-26 02:48:02 +02005706 if (curproxy == &defproxy) {
5707 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005708 err_code |= ERR_ALERT | ERR_FATAL;
5709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005710 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005711 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005712 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005713
Willy Tarreaubaaee002006-06-26 02:48:02 +02005714 if (*(args[1]) == 0) {
5715 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005716 err_code |= ERR_ALERT | ERR_FATAL;
5717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005718 }
5719
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005720 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005721 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5722 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5723 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005724 err_code |= ERR_ALERT | ERR_FATAL;
5725 goto out;
5726 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005727 err_code |= warnif_cond_conflicts(cond,
5728 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5729 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005730 }
5731 else if (*args[2]) {
5732 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5733 file, linenum, args[0], args[2]);
5734 err_code |= ERR_ALERT | ERR_FATAL;
5735 goto out;
5736 }
5737
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005738 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005739 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005740 wl->s = strdup(args[1]);
5741 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005742 }
5743 else if (!strcmp(args[0], "errorloc") ||
5744 !strcmp(args[0], "errorloc302") ||
5745 !strcmp(args[0], "errorloc303")) { /* error location */
5746 int errnum, errlen;
5747 char *err;
5748
Willy Tarreau977b8e42006-12-29 14:19:17 +01005749 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005750 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005751
Willy Tarreaubaaee002006-06-26 02:48:02 +02005752 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005753 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005754 err_code |= ERR_ALERT | ERR_FATAL;
5755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005756 }
5757
5758 errnum = atol(args[1]);
5759 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005760 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5761 err = malloc(errlen);
5762 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005763 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005764 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5765 err = malloc(errlen);
5766 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005767 }
5768
Willy Tarreau0f772532006-12-23 20:51:41 +01005769 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5770 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005771 chunk_destroy(&curproxy->errmsg[rc]);
5772 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005773 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005774 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005775 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005776
5777 if (rc >= HTTP_ERR_SIZE) {
5778 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5779 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005780 free(err);
5781 }
5782 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005783 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5784 int errnum, errlen, fd;
5785 char *err;
5786 struct stat stat;
5787
5788 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005789 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005790
5791 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005792 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005793 err_code |= ERR_ALERT | ERR_FATAL;
5794 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005795 }
5796
5797 fd = open(args[2], O_RDONLY);
5798 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5799 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5800 file, linenum, args[2], args[1]);
5801 if (fd >= 0)
5802 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005803 err_code |= ERR_ALERT | ERR_FATAL;
5804 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005805 }
5806
Willy Tarreau27a674e2009-08-17 07:23:33 +02005807 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005808 errlen = stat.st_size;
5809 } else {
5810 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005811 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005812 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005813 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005814 }
5815
5816 err = malloc(errlen); /* malloc() must succeed during parsing */
5817 errnum = read(fd, err, errlen);
5818 if (errnum != errlen) {
5819 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5820 file, linenum, args[2], args[1]);
5821 close(fd);
5822 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005823 err_code |= ERR_ALERT | ERR_FATAL;
5824 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005825 }
5826 close(fd);
5827
5828 errnum = atol(args[1]);
5829 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5830 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005831 chunk_destroy(&curproxy->errmsg[rc]);
5832 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005833 break;
5834 }
5835 }
5836
5837 if (rc >= HTTP_ERR_SIZE) {
5838 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5839 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005840 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005841 free(err);
5842 }
5843 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005844 else if (!strcmp(args[0], "compression")) {
5845 struct comp *comp;
5846 if (curproxy->comp == NULL) {
5847 comp = calloc(1, sizeof(struct comp));
5848 curproxy->comp = comp;
5849 } else {
5850 comp = curproxy->comp;
5851 }
5852
5853 if (!strcmp(args[1], "algo")) {
5854 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005855 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005856
William Lallemand82fe75c2012-10-23 10:25:10 +02005857 cur_arg = 2;
5858 if (!*args[cur_arg]) {
5859 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5860 file, linenum, args[0]);
5861 err_code |= ERR_ALERT | ERR_FATAL;
5862 goto out;
5863 }
5864 while (*(args[cur_arg])) {
5865 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5866 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5867 file, linenum, args[0], args[cur_arg]);
5868 err_code |= ERR_ALERT | ERR_FATAL;
5869 goto out;
5870 }
William Lallemand552df672012-11-07 13:21:47 +01005871 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5872 curproxy->comp->algos->end(&ctx);
5873 } else {
5874 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5875 file, linenum, args[0], args[cur_arg]);
5876 err_code |= ERR_ALERT | ERR_FATAL;
5877 goto out;
5878 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005879 cur_arg ++;
5880 continue;
5881 }
5882 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005883 else if (!strcmp(args[1], "offload")) {
5884 comp->offload = 1;
5885 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005886 else if (!strcmp(args[1], "type")) {
5887 int cur_arg;
5888 cur_arg = 2;
5889 if (!*args[cur_arg]) {
5890 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5891 file, linenum, args[0]);
5892 err_code |= ERR_ALERT | ERR_FATAL;
5893 goto out;
5894 }
5895 while (*(args[cur_arg])) {
5896 comp_append_type(comp, args[cur_arg]);
5897 cur_arg ++;
5898 continue;
5899 }
5900 }
5901 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005902 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005903 file, linenum, args[0]);
5904 err_code |= ERR_ALERT | ERR_FATAL;
5905 goto out;
5906 }
5907 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005908 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005909 struct cfg_kw_list *kwl;
5910 int index;
5911
5912 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5913 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5914 if (kwl->kw[index].section != CFG_LISTEN)
5915 continue;
5916 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5917 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005918 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005919 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005920 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005921 err_code |= ERR_ALERT | ERR_FATAL;
5922 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005923 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005924 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005925 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005926 err_code |= ERR_WARN;
5927 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005928 }
Willy Tarreau93893792009-07-23 13:19:11 +02005929 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005930 }
5931 }
5932 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005933
Willy Tarreau6daf3432008-01-22 16:44:08 +01005934 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005935 err_code |= ERR_ALERT | ERR_FATAL;
5936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005937 }
Willy Tarreau93893792009-07-23 13:19:11 +02005938 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005939 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005940 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005941}
5942
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005943int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005944cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
5945{
5946#ifdef CONFIG_HAP_NS
5947 const char *err;
5948 const char *item = args[0];
5949
5950 if (!strcmp(item, "namespace_list")) {
5951 return 0;
5952 }
5953 else if (!strcmp(item, "namespace")) {
5954 size_t idx = 1;
5955 const char *current;
5956 while (*(current = args[idx++])) {
5957 err = invalid_char(current);
5958 if (err) {
5959 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5960 file, linenum, *err, item, current);
5961 return ERR_ALERT | ERR_FATAL;
5962 }
5963
5964 if (netns_store_lookup(current, strlen(current))) {
5965 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
5966 file, linenum, current);
5967 return ERR_ALERT | ERR_FATAL;
5968 }
5969 if (!netns_store_insert(current)) {
5970 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
5971 file, linenum, current);
5972 return ERR_ALERT | ERR_FATAL;
5973 }
5974 }
5975 }
5976
5977 return 0;
5978#else
5979 Alert("parsing [%s:%d]: namespace support is not compiled in.",
5980 file, linenum);
5981 return ERR_ALERT | ERR_FATAL;
5982#endif
5983}
5984
5985int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005986cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5987{
5988
5989 int err_code = 0;
5990 const char *err;
5991
5992 if (!strcmp(args[0], "userlist")) { /* new userlist */
5993 struct userlist *newul;
5994
5995 if (!*args[1]) {
5996 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5997 file, linenum, args[0]);
5998 err_code |= ERR_ALERT | ERR_FATAL;
5999 goto out;
6000 }
6001
6002 err = invalid_char(args[1]);
6003 if (err) {
6004 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6005 file, linenum, *err, args[0], args[1]);
6006 err_code |= ERR_ALERT | ERR_FATAL;
6007 goto out;
6008 }
6009
6010 for (newul = userlist; newul; newul = newul->next)
6011 if (!strcmp(newul->name, args[1])) {
6012 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6013 file, linenum, args[1]);
6014 err_code |= ERR_WARN;
6015 goto out;
6016 }
6017
6018 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6019 if (!newul) {
6020 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6021 err_code |= ERR_ALERT | ERR_ABORT;
6022 goto out;
6023 }
6024
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006025 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006026 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006027 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6028 err_code |= ERR_ALERT | ERR_ABORT;
6029 goto out;
6030 }
6031
6032 newul->next = userlist;
6033 userlist = newul;
6034
6035 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006036 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006037 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006038 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006039
6040 if (!*args[1]) {
6041 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6042 file, linenum, args[0]);
6043 err_code |= ERR_ALERT | ERR_FATAL;
6044 goto out;
6045 }
6046
6047 err = invalid_char(args[1]);
6048 if (err) {
6049 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6050 file, linenum, *err, args[0], args[1]);
6051 err_code |= ERR_ALERT | ERR_FATAL;
6052 goto out;
6053 }
6054
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006055 for (ag = userlist->groups; ag; ag = ag->next)
6056 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006057 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6058 file, linenum, args[1], userlist->name);
6059 err_code |= ERR_ALERT;
6060 goto out;
6061 }
6062
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006063 ag = calloc(1, sizeof(*ag));
6064 if (!ag) {
6065 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6066 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006067 goto out;
6068 }
6069
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006070 ag->name = strdup(args[1]);
6071 if (!ag) {
6072 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6073 err_code |= ERR_ALERT | ERR_ABORT;
6074 goto out;
6075 }
6076
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006077 cur_arg = 2;
6078
6079 while (*args[cur_arg]) {
6080 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006081 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006082 cur_arg += 2;
6083 continue;
6084 } else {
6085 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6086 file, linenum, args[0]);
6087 err_code |= ERR_ALERT | ERR_FATAL;
6088 goto out;
6089 }
6090 }
6091
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006092 ag->next = userlist->groups;
6093 userlist->groups = ag;
6094
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006095 } else if (!strcmp(args[0], "user")) { /* new user */
6096 struct auth_users *newuser;
6097 int cur_arg;
6098
6099 if (!*args[1]) {
6100 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6101 file, linenum, args[0]);
6102 err_code |= ERR_ALERT | ERR_FATAL;
6103 goto out;
6104 }
6105
6106 for (newuser = userlist->users; newuser; newuser = newuser->next)
6107 if (!strcmp(newuser->user, args[1])) {
6108 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6109 file, linenum, args[1], userlist->name);
6110 err_code |= ERR_ALERT;
6111 goto out;
6112 }
6113
6114 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6115 if (!newuser) {
6116 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6117 err_code |= ERR_ALERT | ERR_ABORT;
6118 goto out;
6119 }
6120
6121 newuser->user = strdup(args[1]);
6122
6123 newuser->next = userlist->users;
6124 userlist->users = newuser;
6125
6126 cur_arg = 2;
6127
6128 while (*args[cur_arg]) {
6129 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006130#ifdef CONFIG_HAP_CRYPT
6131 if (!crypt("", args[cur_arg + 1])) {
6132 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6133 file, linenum, newuser->user);
6134 err_code |= ERR_ALERT | ERR_FATAL;
6135 goto out;
6136 }
6137#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006138 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6139 file, linenum);
6140 err_code |= ERR_ALERT;
6141#endif
6142 newuser->pass = strdup(args[cur_arg + 1]);
6143 cur_arg += 2;
6144 continue;
6145 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6146 newuser->pass = strdup(args[cur_arg + 1]);
6147 newuser->flags |= AU_O_INSECURE;
6148 cur_arg += 2;
6149 continue;
6150 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006151 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006152 cur_arg += 2;
6153 continue;
6154 } else {
6155 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6156 file, linenum, args[0]);
6157 err_code |= ERR_ALERT | ERR_FATAL;
6158 goto out;
6159 }
6160 }
6161 } else {
6162 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6163 err_code |= ERR_ALERT | ERR_FATAL;
6164 }
6165
6166out:
6167 return err_code;
6168}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006169
6170/*
6171 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006172 * Returns the error code, 0 if OK, or any combination of :
6173 * - ERR_ABORT: must abort ASAP
6174 * - ERR_FATAL: we can continue parsing but not start the service
6175 * - ERR_WARN: a warning has been emitted
6176 * - ERR_ALERT: an alert has been emitted
6177 * Only the two first ones can stop processing, the two others are just
6178 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006179 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006180int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006181{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006182 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006183 FILE *f;
6184 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006185 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006186 struct cfg_section *cs = NULL;
6187 struct cfg_section *ics;
6188
6189 /* Register internal sections */
6190 if (!cfg_register_section("listen", cfg_parse_listen) ||
6191 !cfg_register_section("frontend", cfg_parse_listen) ||
6192 !cfg_register_section("backend", cfg_parse_listen) ||
6193 !cfg_register_section("ruleset", cfg_parse_listen) ||
6194 !cfg_register_section("defaults", cfg_parse_listen) ||
6195 !cfg_register_section("global", cfg_parse_global) ||
6196 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006197 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006198 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006199 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006200 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006201
Willy Tarreaubaaee002006-06-26 02:48:02 +02006202 if ((f=fopen(file,"r")) == NULL)
6203 return -1;
6204
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006205 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006206 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006207 char *end;
6208 char *args[MAX_LINE_ARGS + 1];
6209 char *line = thisline;
6210
Willy Tarreaubaaee002006-06-26 02:48:02 +02006211 linenum++;
6212
6213 end = line + strlen(line);
6214
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006215 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6216 /* Check if we reached the limit and the last char is not \n.
6217 * Watch out for the last line without the terminating '\n'!
6218 */
6219 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006220 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006221 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006222 }
6223
Willy Tarreaubaaee002006-06-26 02:48:02 +02006224 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006225 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006226 line++;
6227
6228 arg = 0;
6229 args[arg] = line;
6230
6231 while (*line && arg < MAX_LINE_ARGS) {
6232 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6233 * C equivalent value. Other combinations left unchanged (eg: \1).
6234 */
6235 if (*line == '\\') {
6236 int skip = 0;
6237 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6238 *line = line[1];
6239 skip = 1;
6240 }
6241 else if (line[1] == 'r') {
6242 *line = '\r';
6243 skip = 1;
6244 }
6245 else if (line[1] == 'n') {
6246 *line = '\n';
6247 skip = 1;
6248 }
6249 else if (line[1] == 't') {
6250 *line = '\t';
6251 skip = 1;
6252 }
6253 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006254 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006255 unsigned char hex1, hex2;
6256 hex1 = toupper(line[2]) - '0';
6257 hex2 = toupper(line[3]) - '0';
6258 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6259 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6260 *line = (hex1<<4) + hex2;
6261 skip = 3;
6262 }
6263 else {
6264 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006265 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006266 }
6267 }
6268 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006269 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006270 end -= skip;
6271 }
6272 line++;
6273 }
6274 else if (*line == '#' || *line == '\n' || *line == '\r') {
6275 /* end of string, end of loop */
6276 *line = 0;
6277 break;
6278 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006279 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006280 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006281 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006282 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006283 line++;
6284 args[++arg] = line;
6285 }
6286 else {
6287 line++;
6288 }
6289 }
6290
6291 /* empty line */
6292 if (!**args)
6293 continue;
6294
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006295 if (*line) {
6296 /* we had to stop due to too many args.
6297 * Let's terminate the string, print the offending part then cut the
6298 * last arg.
6299 */
6300 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6301 line++;
6302 *line = '\0';
6303
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006304 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006305 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006306 err_code |= ERR_ALERT | ERR_FATAL;
6307 args[arg] = line;
6308 }
6309
Willy Tarreau540abe42007-05-02 20:50:16 +02006310 /* zero out remaining args and ensure that at least one entry
6311 * is zeroed out.
6312 */
6313 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006314 args[arg] = line;
6315 }
6316
Willy Tarreau3842f002009-06-14 11:39:52 +02006317 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006318 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006319 char *tmp;
6320
Willy Tarreau3842f002009-06-14 11:39:52 +02006321 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006322 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006323 for (arg=0; *args[arg+1]; arg++)
6324 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006325 *tmp = '\0'; // fix the next arg to \0
6326 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006327 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006328 else if (!strcmp(args[0], "default")) {
6329 kwm = KWM_DEF;
6330 for (arg=0; *args[arg+1]; arg++)
6331 args[arg] = args[arg+1]; // shift args after inversion
6332 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006333
William Lallemand0f99e342011-10-12 17:50:54 +02006334 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6335 strcmp(args[0], "log") != 0) {
6336 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006337 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006338 }
6339
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006340 /* detect section start */
6341 list_for_each_entry(ics, &sections, list) {
6342 if (strcmp(args[0], ics->section_name) == 0) {
6343 cursection = ics->section_name;
6344 cs = ics;
6345 break;
6346 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006347 }
6348
Willy Tarreaubaaee002006-06-26 02:48:02 +02006349 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006350 if (cs)
6351 err_code |= cs->section_parser(file, linenum, args, kwm);
6352 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006353 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006354 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006355 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006356
6357 if (err_code & ERR_ABORT)
6358 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006359 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006360 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006361 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006362 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006363}
6364
Willy Tarreau64ab6072014-09-16 12:17:36 +02006365/* This function propagates processes from frontend <from> to backend <to> so
6366 * that it is always guaranteed that a backend pointed to by a frontend is
6367 * bound to all of its processes. After that, if the target is a "listen"
6368 * instance, the function recursively descends the target's own targets along
6369 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6370 * checked first to ensure that <to> is already bound to all processes of
6371 * <from>, there is no risk of looping and we ensure to follow the shortest
6372 * path to the destination.
6373 *
6374 * It is possible to set <to> to NULL for the first call so that the function
6375 * takes care of visiting the initial frontend in <from>.
6376 *
6377 * It is important to note that the function relies on the fact that all names
6378 * have already been resolved.
6379 */
6380void propagate_processes(struct proxy *from, struct proxy *to)
6381{
6382 struct switching_rule *rule;
6383 struct hdr_exp *exp;
6384
6385 if (to) {
6386 /* check whether we need to go down */
6387 if (from->bind_proc &&
6388 (from->bind_proc & to->bind_proc) == from->bind_proc)
6389 return;
6390
6391 if (!from->bind_proc && !to->bind_proc)
6392 return;
6393
6394 to->bind_proc = from->bind_proc ?
6395 (to->bind_proc | from->bind_proc) : 0;
6396
6397 /* now propagate down */
6398 from = to;
6399 }
6400
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006401 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006402 return;
6403
Willy Tarreauf6b70012014-12-18 14:00:43 +01006404 if (from->state == PR_STSTOPPED)
6405 return;
6406
Willy Tarreau64ab6072014-09-16 12:17:36 +02006407 /* default_backend */
6408 if (from->defbe.be)
6409 propagate_processes(from, from->defbe.be);
6410
6411 /* use_backend */
6412 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006413 if (rule->dynamic)
6414 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006415 to = rule->be.backend;
6416 propagate_processes(from, to);
6417 }
6418
6419 /* reqsetbe */
6420 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6421 if (exp->action != ACT_SETBE)
6422 continue;
6423 to = (struct proxy *)exp->replace;
6424 propagate_processes(from, to);
6425 }
6426}
6427
Willy Tarreaubb925012009-07-23 13:36:36 +02006428/*
6429 * Returns the error code, 0 if OK, or any combination of :
6430 * - ERR_ABORT: must abort ASAP
6431 * - ERR_FATAL: we can continue parsing but not start the service
6432 * - ERR_WARN: a warning has been emitted
6433 * - ERR_ALERT: an alert has been emitted
6434 * Only the two first ones can stop processing, the two others are just
6435 * indicators.
6436 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006437int check_config_validity()
6438{
6439 int cfgerr = 0;
6440 struct proxy *curproxy = NULL;
6441 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006442 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006443 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006444 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006445
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006446 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006447 /*
6448 * Now, check for the integrity of all that we have collected.
6449 */
6450
6451 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006452 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006453
Willy Tarreau193b8c62012-11-22 00:17:38 +01006454 if (!global.tune.max_http_hdr)
6455 global.tune.max_http_hdr = MAX_HTTP_HDR;
6456
6457 if (!global.tune.cookie_len)
6458 global.tune.cookie_len = CAPTURE_LEN;
6459
6460 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6461
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006462 /* Post initialisation of the users and groups lists. */
6463 err_code = userlist_postinit();
6464 if (err_code != ERR_NONE)
6465 goto out;
6466
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006467 /* first, we will invert the proxy list order */
6468 curproxy = NULL;
6469 while (proxy) {
6470 struct proxy *next;
6471
6472 next = proxy->next;
6473 proxy->next = curproxy;
6474 curproxy = proxy;
6475 if (!next)
6476 break;
6477 proxy = next;
6478 }
6479
Willy Tarreau419ead82014-09-16 13:41:21 +02006480 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006481 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006482 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006483 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006484 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006485 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006486 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006487 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006488
Willy Tarreau050536d2012-10-04 08:47:34 +02006489 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006490 /* proxy ID not set, use automatic numbering with first
6491 * spare entry starting with next_pxid.
6492 */
6493 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6494 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6495 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006496 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006497 next_pxid++;
6498
Willy Tarreau55ea7572007-06-17 19:56:27 +02006499
Willy Tarreaubaaee002006-06-26 02:48:02 +02006500 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006501 /* ensure we don't keep listeners uselessly bound */
6502 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02006503 free((void *)curproxy->table.peers.name);
6504 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006505 continue;
6506 }
6507
Willy Tarreau102df612014-05-07 23:56:38 +02006508 /* Check multi-process mode compatibility for the current proxy */
6509
6510 if (curproxy->bind_proc) {
6511 /* an explicit bind-process was specified, let's check how many
6512 * processes remain.
6513 */
6514 nbproc = popcount(curproxy->bind_proc);
6515
6516 curproxy->bind_proc &= nbits(global.nbproc);
6517 if (!curproxy->bind_proc && nbproc == 1) {
6518 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);
6519 curproxy->bind_proc = 1;
6520 }
6521 else if (!curproxy->bind_proc && nbproc > 1) {
6522 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);
6523 curproxy->bind_proc = 0;
6524 }
6525 }
6526
Willy Tarreau3d209582014-05-09 17:06:11 +02006527 /* check and reduce the bind-proc of each listener */
6528 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6529 unsigned long mask;
6530
6531 if (!bind_conf->bind_proc)
6532 continue;
6533
6534 mask = nbits(global.nbproc);
6535 if (curproxy->bind_proc)
6536 mask &= curproxy->bind_proc;
6537 /* mask cannot be null here thanks to the previous checks */
6538
6539 nbproc = popcount(bind_conf->bind_proc);
6540 bind_conf->bind_proc &= mask;
6541
6542 if (!bind_conf->bind_proc && nbproc == 1) {
6543 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",
6544 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6545 bind_conf->bind_proc = mask & ~(mask - 1);
6546 }
6547 else if (!bind_conf->bind_proc && nbproc > 1) {
6548 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",
6549 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6550 bind_conf->bind_proc = 0;
6551 }
6552 }
6553
Willy Tarreauff01a212009-03-15 13:46:16 +01006554 switch (curproxy->mode) {
6555 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006556 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006557 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006558 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6559 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006560 cfgerr++;
6561 }
6562
6563 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006564 Warning("config : servers will be ignored for %s '%s'.\n",
6565 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006566 break;
6567
6568 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006569 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006570 break;
6571
6572 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006573 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006574 break;
6575 }
6576
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006577 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006578 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006579 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006580 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6581 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006582 cfgerr++;
6583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006584#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006585 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006586 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6587 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006588 cfgerr++;
6589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006590#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006591 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006592 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6593 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006594 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006595 }
6596 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006597 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006598 /* If no LB algo is set in a backend, and we're not in
6599 * transparent mode, dispatch mode nor proxy mode, we
6600 * want to use balance roundrobin by default.
6601 */
6602 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6603 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006604 }
6605 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006606
Willy Tarreau1620ec32011-08-06 17:05:02 +02006607 if (curproxy->options & PR_O_DISPATCH)
6608 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6609 else if (curproxy->options & PR_O_HTTP_PROXY)
6610 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6611 else if (curproxy->options & PR_O_TRANSP)
6612 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006613
Willy Tarreau1620ec32011-08-06 17:05:02 +02006614 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6615 if (curproxy->options & PR_O_DISABLE404) {
6616 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6617 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6618 err_code |= ERR_WARN;
6619 curproxy->options &= ~PR_O_DISABLE404;
6620 }
6621 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6622 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6623 "send-state", proxy_type_str(curproxy), curproxy->id);
6624 err_code |= ERR_WARN;
6625 curproxy->options &= ~PR_O2_CHK_SNDST;
6626 }
Willy Tarreauef781042010-01-27 11:53:01 +01006627 }
6628
Simon Horman98637e52014-06-20 12:30:16 +09006629 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6630 if (!global.external_check) {
6631 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6632 curproxy->id, "option external-check");
6633 cfgerr++;
6634 }
6635 if (!curproxy->check_command) {
6636 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6637 curproxy->id, "option external-check");
6638 cfgerr++;
6639 }
6640 }
6641
Simon Horman64e34162015-02-06 11:11:57 +09006642 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006643 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
6644 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09006645 "'email-alert from', 'email-alert level' 'email-alert mailer', "
6646 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006647 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
6648 "to be present).\n",
6649 proxy_type_str(curproxy), curproxy->id);
6650 err_code |= ERR_WARN;
6651 free_email_alert(curproxy);
6652 }
6653 if (!curproxy->email_alert.myhostname)
6654 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09006655 }
6656
Simon Horman98637e52014-06-20 12:30:16 +09006657 if (curproxy->check_command) {
6658 int clear = 0;
6659 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6660 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6661 "external-check command", proxy_type_str(curproxy), curproxy->id);
6662 err_code |= ERR_WARN;
6663 clear = 1;
6664 }
6665 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6666 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6667 curproxy->id, "external-check command");
6668 cfgerr++;
6669 }
6670 if (clear) {
6671 free(curproxy->check_command);
6672 curproxy->check_command = NULL;
6673 }
6674 }
6675
6676 if (curproxy->check_path) {
6677 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6678 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6679 "external-check path", proxy_type_str(curproxy), curproxy->id);
6680 err_code |= ERR_WARN;
6681 free(curproxy->check_path);
6682 curproxy->check_path = NULL;
6683 }
6684 }
6685
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006686 /* if a default backend was specified, let's find it */
6687 if (curproxy->defbe.name) {
6688 struct proxy *target;
6689
Alex Williams96532db2009-11-01 21:27:13 -05006690 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006691 if (!target) {
6692 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6693 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006694 cfgerr++;
6695 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006696 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6697 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006698 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006699 } else {
6700 free(curproxy->defbe.name);
6701 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006702
6703 /* Emit a warning if this proxy also has some servers */
6704 if (curproxy->srv) {
6705 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6706 curproxy->id);
6707 err_code |= ERR_WARN;
6708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006709 }
6710 }
6711
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006712 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006713 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6714 /* map jump target for ACT_SETBE in req_rep chain */
6715 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006716 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006717 struct proxy *target;
6718
Willy Tarreaua496b602006-12-17 23:15:24 +01006719 if (exp->action != ACT_SETBE)
6720 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006721
Alex Williams96532db2009-11-01 21:27:13 -05006722 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006723 if (!target) {
6724 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6725 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006726 cfgerr++;
6727 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006728 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6729 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006730 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006731 } else {
6732 free((void *)exp->replace);
6733 exp->replace = (const char *)target;
6734 }
6735 }
6736 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006737
6738 /* find the target proxy for 'use_backend' rules */
6739 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006740 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006741 struct logformat_node *node;
6742 char *pxname;
6743
6744 /* Try to parse the string as a log format expression. If the result
6745 * of the parsing is only one entry containing a simple string, then
6746 * it's a standard string corresponding to a static rule, thus the
6747 * parsing is cancelled and be.name is restored to be resolved.
6748 */
6749 pxname = rule->be.name;
6750 LIST_INIT(&rule->be.expr);
6751 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6752 curproxy->conf.args.file, curproxy->conf.args.line);
6753 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6754
6755 if (!LIST_ISEMPTY(&rule->be.expr)) {
6756 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6757 rule->dynamic = 1;
6758 free(pxname);
6759 continue;
6760 }
6761 /* simple string: free the expression and fall back to static rule */
6762 free(node->arg);
6763 free(node);
6764 }
6765
6766 rule->dynamic = 0;
6767 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006768
Alex Williams96532db2009-11-01 21:27:13 -05006769 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006770
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006771 if (!target) {
6772 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6773 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006774 cfgerr++;
6775 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006776 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6777 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006778 cfgerr++;
6779 } else {
6780 free((void *)rule->be.name);
6781 rule->be.backend = target;
6782 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006783 }
6784
Willy Tarreau64ab6072014-09-16 12:17:36 +02006785 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006786 list_for_each_entry(srule, &curproxy->server_rules, list) {
6787 struct server *target = findserver(curproxy, srule->srv.name);
6788
6789 if (!target) {
6790 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6791 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6792 cfgerr++;
6793 continue;
6794 }
6795 free((void *)srule->srv.name);
6796 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006797 }
6798
Emeric Brunb982a3d2010-01-04 15:45:53 +01006799 /* find the target table for 'stick' rules */
6800 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6801 struct proxy *target;
6802
Emeric Brun1d33b292010-01-04 15:47:17 +01006803 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6804 if (mrule->flags & STK_IS_STORE)
6805 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6806
Emeric Brunb982a3d2010-01-04 15:45:53 +01006807 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006808 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006809 else
6810 target = curproxy;
6811
6812 if (!target) {
6813 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6814 curproxy->id, mrule->table.name);
6815 cfgerr++;
6816 }
6817 else if (target->table.size == 0) {
6818 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6819 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6820 cfgerr++;
6821 }
Willy Tarreau12785782012-04-27 21:37:17 +02006822 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6823 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006824 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6825 cfgerr++;
6826 }
6827 else {
6828 free((void *)mrule->table.name);
6829 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006830 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006831 }
6832 }
6833
6834 /* find the target table for 'store response' rules */
6835 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6836 struct proxy *target;
6837
Emeric Brun1d33b292010-01-04 15:47:17 +01006838 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6839
Emeric Brunb982a3d2010-01-04 15:45:53 +01006840 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006841 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006842 else
6843 target = curproxy;
6844
6845 if (!target) {
6846 Alert("Proxy '%s': unable to find store table '%s'.\n",
6847 curproxy->id, mrule->table.name);
6848 cfgerr++;
6849 }
6850 else if (target->table.size == 0) {
6851 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6852 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6853 cfgerr++;
6854 }
Willy Tarreau12785782012-04-27 21:37:17 +02006855 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6856 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006857 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6858 cfgerr++;
6859 }
6860 else {
6861 free((void *)mrule->table.name);
6862 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006863 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006864 }
6865 }
6866
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006867 /* find the target table for 'tcp-request' layer 4 rules */
6868 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6869 struct proxy *target;
6870
Willy Tarreaub4c84932013-07-23 19:15:30 +02006871 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006872 continue;
6873
6874 if (trule->act_prm.trk_ctr.table.n)
6875 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6876 else
6877 target = curproxy;
6878
6879 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006880 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6881 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006882 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006883 cfgerr++;
6884 }
6885 else if (target->table.size == 0) {
6886 Alert("Proxy '%s': table '%s' used but not configured.\n",
6887 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6888 cfgerr++;
6889 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006890 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6891 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6892 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 +01006893 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006894 cfgerr++;
6895 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006896 else {
6897 free(trule->act_prm.trk_ctr.table.n);
6898 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006899 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006900 * to pass a list of counters to track and allocate them right here using
6901 * stktable_alloc_data_type().
6902 */
6903 }
6904 }
6905
Willy Tarreaud1f96522010-08-03 19:34:32 +02006906 /* find the target table for 'tcp-request' layer 6 rules */
6907 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6908 struct proxy *target;
6909
Willy Tarreaub4c84932013-07-23 19:15:30 +02006910 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006911 continue;
6912
6913 if (trule->act_prm.trk_ctr.table.n)
6914 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6915 else
6916 target = curproxy;
6917
6918 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006919 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6920 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006921 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006922 cfgerr++;
6923 }
6924 else if (target->table.size == 0) {
6925 Alert("Proxy '%s': table '%s' used but not configured.\n",
6926 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6927 cfgerr++;
6928 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006929 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6930 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6931 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 +01006932 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006933 cfgerr++;
6934 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006935 else {
6936 free(trule->act_prm.trk_ctr.table.n);
6937 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006938 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006939 * to pass a list of counters to track and allocate them right here using
6940 * stktable_alloc_data_type().
6941 */
6942 }
6943 }
6944
Willy Tarreau09448f72014-06-25 18:12:15 +02006945 /* find the target table for 'http-request' layer 7 rules */
6946 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6947 struct proxy *target;
6948
6949 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6950 continue;
6951
6952 if (hrqrule->act_prm.trk_ctr.table.n)
6953 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6954 else
6955 target = curproxy;
6956
6957 if (!target) {
6958 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6959 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6960 http_req_trk_idx(hrqrule->action));
6961 cfgerr++;
6962 }
6963 else if (target->table.size == 0) {
6964 Alert("Proxy '%s': table '%s' used but not configured.\n",
6965 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6966 cfgerr++;
6967 }
6968 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6969 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6970 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6971 http_req_trk_idx(hrqrule->action));
6972 cfgerr++;
6973 }
6974 else {
6975 free(hrqrule->act_prm.trk_ctr.table.n);
6976 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6977 /* Note: if we decide to enhance the track-sc syntax, we may be able
6978 * to pass a list of counters to track and allocate them right here using
6979 * stktable_alloc_data_type().
6980 */
6981 }
6982 }
6983
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006984 /* move any "block" rules at the beginning of the http-request rules */
6985 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6986 /* insert block_rules into http_req_rules at the beginning */
6987 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6988 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6989 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6990 curproxy->http_req_rules.n = curproxy->block_rules.n;
6991 LIST_INIT(&curproxy->block_rules);
6992 }
6993
Emeric Brun32da3c42010-09-23 18:39:19 +02006994 if (curproxy->table.peers.name) {
6995 struct peers *curpeers = peers;
6996
6997 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6998 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6999 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007000 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007001 break;
7002 }
7003 }
7004
7005 if (!curpeers) {
7006 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7007 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007008 free((void *)curproxy->table.peers.name);
7009 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007010 cfgerr++;
7011 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007012 else if (curpeers->state == PR_STSTOPPED) {
7013 /* silently disable this peers section */
7014 curproxy->table.peers.p = NULL;
7015 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007016 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007017 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7018 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007019 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007020 cfgerr++;
7021 }
7022 }
7023
Simon Horman9dc49962015-01-30 11:22:59 +09007024
7025 if (curproxy->email_alert.mailers.name) {
7026 struct mailers *curmailers = mailers;
7027
7028 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7029 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7030 free(curproxy->email_alert.mailers.name);
7031 curproxy->email_alert.mailers.m = curmailers;
7032 curmailers->users++;
7033 break;
7034 }
7035 }
7036
7037 if (!curmailers) {
7038 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7039 curproxy->id, curproxy->email_alert.mailers.name);
7040 free_email_alert(curproxy);
7041 cfgerr++;
7042 }
7043 }
7044
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007045 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007046 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007047 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7048 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7049 "proxy", curproxy->id);
7050 cfgerr++;
7051 goto out_uri_auth_compat;
7052 }
7053
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007054 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007055 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007056 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007057 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007058
Willy Tarreau95fa4692010-02-01 13:05:50 +01007059 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7060 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007061
7062 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007063 uri_auth_compat_req[i++] = "realm";
7064 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7065 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007066
Willy Tarreau95fa4692010-02-01 13:05:50 +01007067 uri_auth_compat_req[i++] = "unless";
7068 uri_auth_compat_req[i++] = "{";
7069 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7070 uri_auth_compat_req[i++] = "}";
7071 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007072
Willy Tarreauff011f22011-01-06 17:51:27 +01007073 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7074 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007075 cfgerr++;
7076 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007077 }
7078
Willy Tarreauff011f22011-01-06 17:51:27 +01007079 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007080
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007081 if (curproxy->uri_auth->auth_realm) {
7082 free(curproxy->uri_auth->auth_realm);
7083 curproxy->uri_auth->auth_realm = NULL;
7084 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007085
7086 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007087 }
7088out_uri_auth_compat:
7089
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007090 /* compile the log format */
7091 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007092 if (curproxy->conf.logformat_string != default_http_log_format &&
7093 curproxy->conf.logformat_string != default_tcp_log_format &&
7094 curproxy->conf.logformat_string != clf_http_log_format)
7095 free(curproxy->conf.logformat_string);
7096 curproxy->conf.logformat_string = NULL;
7097 free(curproxy->conf.lfs_file);
7098 curproxy->conf.lfs_file = NULL;
7099 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007100 }
7101
Willy Tarreau62a61232013-04-12 18:13:46 +02007102 if (curproxy->conf.logformat_string) {
7103 curproxy->conf.args.ctx = ARGC_LOG;
7104 curproxy->conf.args.file = curproxy->conf.lfs_file;
7105 curproxy->conf.args.line = curproxy->conf.lfs_line;
7106 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007107 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007108 curproxy->conf.args.file = NULL;
7109 curproxy->conf.args.line = 0;
7110 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007111
Willy Tarreau62a61232013-04-12 18:13:46 +02007112 if (curproxy->conf.uniqueid_format_string) {
7113 curproxy->conf.args.ctx = ARGC_UIF;
7114 curproxy->conf.args.file = curproxy->conf.uif_file;
7115 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007116 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007117 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007118 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007119 curproxy->conf.args.file = NULL;
7120 curproxy->conf.args.line = 0;
7121 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007122
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007123 /* only now we can check if some args remain unresolved.
7124 * This must be done after the users and groups resolution.
7125 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007126 cfgerr += smp_resolve_args(curproxy);
7127 if (!cfgerr)
7128 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007129
Willy Tarreau2738a142006-07-08 17:28:09 +02007130 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007131 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007132 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007133 (!curproxy->timeout.connect ||
7134 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007135 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007136 " | While not properly invalid, you will certainly encounter various problems\n"
7137 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007138 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007139 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007140 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007141 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007142
Willy Tarreau1fa31262007-12-03 00:36:16 +01007143 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7144 * We must still support older configurations, so let's find out whether those
7145 * parameters have been set or must be copied from contimeouts.
7146 */
7147 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007148 if (!curproxy->timeout.tarpit ||
7149 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007150 /* tarpit timeout not set. We search in the following order:
7151 * default.tarpit, curr.connect, default.connect.
7152 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007153 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007154 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007155 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007156 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007157 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007158 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007159 }
7160 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007161 (!curproxy->timeout.queue ||
7162 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007163 /* queue timeout not set. We search in the following order:
7164 * default.queue, curr.connect, default.connect.
7165 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007166 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007167 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007168 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007169 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007170 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007171 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007172 }
7173 }
7174
Willy Tarreau1620ec32011-08-06 17:05:02 +02007175 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007176 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7177 curproxy->check_req = (char *)malloc(curproxy->check_len);
7178 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007179 }
7180
Willy Tarreau215663d2014-06-13 18:30:23 +02007181 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7182 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7183 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7184 proxy_type_str(curproxy), curproxy->id);
7185 err_code |= ERR_WARN;
7186 }
7187
Willy Tarreau193b8c62012-11-22 00:17:38 +01007188 /* ensure that cookie capture length is not too large */
7189 if (curproxy->capture_len >= global.tune.cookie_len) {
7190 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7191 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7192 err_code |= ERR_WARN;
7193 curproxy->capture_len = global.tune.cookie_len - 1;
7194 }
7195
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007196 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007197 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007198 curproxy->req_cap_pool = create_pool("ptrcap",
7199 curproxy->nb_req_cap * sizeof(char *),
7200 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007201 }
7202
7203 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007204 curproxy->rsp_cap_pool = create_pool("ptrcap",
7205 curproxy->nb_rsp_cap * sizeof(char *),
7206 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007207 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007208
Willy Tarreaubaaee002006-06-26 02:48:02 +02007209 /* first, we will invert the servers list order */
7210 newsrv = NULL;
7211 while (curproxy->srv) {
7212 struct server *next;
7213
7214 next = curproxy->srv->next;
7215 curproxy->srv->next = newsrv;
7216 newsrv = curproxy->srv;
7217 if (!next)
7218 break;
7219 curproxy->srv = next;
7220 }
7221
Willy Tarreau17edc812014-01-03 12:14:34 +01007222 /* Check that no server name conflicts. This causes trouble in the stats.
7223 * We only emit a warning for the first conflict affecting each server,
7224 * in order to avoid combinatory explosion if all servers have the same
7225 * name. We do that only for servers which do not have an explicit ID,
7226 * because these IDs were made also for distinguishing them and we don't
7227 * want to annoy people who correctly manage them.
7228 */
7229 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7230 struct server *other_srv;
7231
7232 if (newsrv->puid)
7233 continue;
7234
7235 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7236 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7237 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7238 newsrv->conf.file, newsrv->conf.line,
7239 proxy_type_str(curproxy), curproxy->id,
7240 newsrv->id, other_srv->conf.line);
7241 break;
7242 }
7243 }
7244 }
7245
Willy Tarreaudd701652010-05-25 23:03:02 +02007246 /* assign automatic UIDs to servers which don't have one yet */
7247 next_id = 1;
7248 newsrv = curproxy->srv;
7249 while (newsrv != NULL) {
7250 if (!newsrv->puid) {
7251 /* server ID not set, use automatic numbering with first
7252 * spare entry starting with next_svid.
7253 */
7254 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7255 newsrv->conf.id.key = newsrv->puid = next_id;
7256 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7257 }
7258 next_id++;
7259 newsrv = newsrv->next;
7260 }
7261
Willy Tarreau20697042007-11-15 23:26:18 +01007262 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007263 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007264
Willy Tarreau62c3be22012-01-20 13:12:32 +01007265 /*
7266 * If this server supports a maxconn parameter, it needs a dedicated
7267 * tasks to fill the emptied slots when a connection leaves.
7268 * Also, resolve deferred tracking dependency if needed.
7269 */
7270 newsrv = curproxy->srv;
7271 while (newsrv != NULL) {
7272 if (newsrv->minconn > newsrv->maxconn) {
7273 /* Only 'minconn' was specified, or it was higher than or equal
7274 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7275 * this will avoid further useless expensive computations.
7276 */
7277 newsrv->maxconn = newsrv->minconn;
7278 } else if (newsrv->maxconn && !newsrv->minconn) {
7279 /* minconn was not specified, so we set it to maxconn */
7280 newsrv->minconn = newsrv->maxconn;
7281 }
7282
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007283#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007284 if (newsrv->use_ssl || newsrv->check.use_ssl)
7285 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007286#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007287
Willy Tarreau2f075e92013-12-03 11:11:34 +01007288 /* set the check type on the server */
7289 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7290
Willy Tarreau62c3be22012-01-20 13:12:32 +01007291 if (newsrv->trackit) {
7292 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007293 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007294 char *pname, *sname;
7295
7296 pname = newsrv->trackit;
7297 sname = strrchr(pname, '/');
7298
7299 if (sname)
7300 *sname++ = '\0';
7301 else {
7302 sname = pname;
7303 pname = NULL;
7304 }
7305
7306 if (pname) {
7307 px = findproxy(pname, PR_CAP_BE);
7308 if (!px) {
7309 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7310 proxy_type_str(curproxy), curproxy->id,
7311 newsrv->id, pname);
7312 cfgerr++;
7313 goto next_srv;
7314 }
7315 } else
7316 px = curproxy;
7317
7318 srv = findserver(px, sname);
7319 if (!srv) {
7320 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7321 proxy_type_str(curproxy), curproxy->id,
7322 newsrv->id, sname);
7323 cfgerr++;
7324 goto next_srv;
7325 }
7326
Willy Tarreau32091232014-05-16 13:52:00 +02007327 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7328 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7329 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007330 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007331 "tracking as it does not have any check nor agent enabled.\n",
7332 proxy_type_str(curproxy), curproxy->id,
7333 newsrv->id, px->id, srv->id);
7334 cfgerr++;
7335 goto next_srv;
7336 }
7337
7338 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7339
7340 if (loop) {
7341 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7342 "belongs to a tracking chain looping back to %s/%s.\n",
7343 proxy_type_str(curproxy), curproxy->id,
7344 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007345 cfgerr++;
7346 goto next_srv;
7347 }
7348
7349 if (curproxy != px &&
7350 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7351 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7352 "tracking: disable-on-404 option inconsistency.\n",
7353 proxy_type_str(curproxy), curproxy->id,
7354 newsrv->id, px->id, srv->id);
7355 cfgerr++;
7356 goto next_srv;
7357 }
7358
7359 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007360 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007361 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007362 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007363 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007364 }
7365
7366 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007367 newsrv->tracknext = srv->trackers;
7368 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007369
7370 free(newsrv->trackit);
7371 newsrv->trackit = NULL;
7372 }
7373 next_srv:
7374 newsrv = newsrv->next;
7375 }
7376
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007377 /* We have to initialize the server lookup mechanism depending
7378 * on what LB algorithm was choosen.
7379 */
7380
7381 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7382 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7383 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007384 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7385 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7386 init_server_map(curproxy);
7387 } else {
7388 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7389 fwrr_init_server_groups(curproxy);
7390 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007391 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007392
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007393 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007394 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7395 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7396 fwlc_init_server_tree(curproxy);
7397 } else {
7398 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7399 fas_init_server_tree(curproxy);
7400 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007401 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007402
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007403 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007404 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7405 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7406 chash_init_server_tree(curproxy);
7407 } else {
7408 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7409 init_server_map(curproxy);
7410 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007411 break;
7412 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007413
7414 if (curproxy->options & PR_O_LOGASAP)
7415 curproxy->to_log &= ~LW_BYTES;
7416
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007417 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007418 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007419 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7420 proxy_type_str(curproxy), curproxy->id);
7421 err_code |= ERR_WARN;
7422 }
7423
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007424 if (curproxy->mode != PR_MODE_HTTP) {
7425 int optnum;
7426
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007427 if (curproxy->uri_auth) {
7428 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7429 proxy_type_str(curproxy), curproxy->id);
7430 err_code |= ERR_WARN;
7431 curproxy->uri_auth = NULL;
7432 }
7433
Willy Tarreau87cf5142011-08-19 22:57:24 +02007434 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007435 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7436 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7437 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007438 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007439 }
7440
7441 if (curproxy->options & PR_O_ORGTO) {
7442 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7443 "originalto", proxy_type_str(curproxy), curproxy->id);
7444 err_code |= ERR_WARN;
7445 curproxy->options &= ~PR_O_ORGTO;
7446 }
7447
7448 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7449 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7450 (curproxy->cap & cfg_opts[optnum].cap) &&
7451 (curproxy->options & cfg_opts[optnum].val)) {
7452 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7453 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7454 err_code |= ERR_WARN;
7455 curproxy->options &= ~cfg_opts[optnum].val;
7456 }
7457 }
7458
7459 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7460 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7461 (curproxy->cap & cfg_opts2[optnum].cap) &&
7462 (curproxy->options2 & cfg_opts2[optnum].val)) {
7463 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7464 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7465 err_code |= ERR_WARN;
7466 curproxy->options2 &= ~cfg_opts2[optnum].val;
7467 }
7468 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007469
Pieter Baauwd551fb52013-05-08 22:49:23 +02007470#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007471 if (curproxy->conn_src.bind_hdr_occ) {
7472 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007473 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007474 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007475 err_code |= ERR_WARN;
7476 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007477#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007478 }
7479
Willy Tarreaubaaee002006-06-26 02:48:02 +02007480 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007481 * ensure that we're not cross-dressing a TCP server into HTTP.
7482 */
7483 newsrv = curproxy->srv;
7484 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007485 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007486 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7487 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007488 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007489 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007490
Willy Tarreau0cec3312011-10-31 13:49:26 +01007491 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7492 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7493 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7494 err_code |= ERR_WARN;
7495 }
7496
Willy Tarreauc93cd162014-05-13 15:54:22 +02007497 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007498 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7499 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7500 err_code |= ERR_WARN;
7501 }
7502
Pieter Baauwd551fb52013-05-08 22:49:23 +02007503#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007504 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7505 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007506 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 +01007507 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007508 err_code |= ERR_WARN;
7509 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007510#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007511 newsrv = newsrv->next;
7512 }
7513
Willy Tarreaue42bd962014-09-16 16:21:19 +02007514 /* check if we have a frontend with "tcp-request content" looking at L7
7515 * with no inspect-delay
7516 */
7517 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7518 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7519 if (trule->action == TCP_ACT_CAPTURE &&
7520 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7521 break;
7522 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7523 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7524 break;
7525 }
7526
7527 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7528 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7529 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7530 " This means that these rules will randomly find their contents. This can be fixed by"
7531 " setting the tcp-request inspect-delay.\n",
7532 proxy_type_str(curproxy), curproxy->id);
7533 err_code |= ERR_WARN;
7534 }
7535 }
7536
Willy Tarreauc1a21672009-08-16 22:37:44 +02007537 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007538 if (!curproxy->accept)
7539 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007540
Willy Tarreauc1a21672009-08-16 22:37:44 +02007541 if (curproxy->tcp_req.inspect_delay ||
7542 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007543 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007544
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007545 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007546 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007547 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007548 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007549
7550 /* both TCP and HTTP must check switching rules */
7551 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7552 }
7553
7554 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007555 if (curproxy->tcp_req.inspect_delay ||
7556 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7557 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7558
Emeric Brun97679e72010-09-23 17:56:44 +02007559 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7560 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7561
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007562 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007563 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007564 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007565 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007566
7567 /* If the backend does requires RDP cookie persistence, we have to
7568 * enable the corresponding analyser.
7569 */
7570 if (curproxy->options2 & PR_O2_RDPC_PRST)
7571 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7572 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007573 }
7574
7575 /***********************************************************/
7576 /* At this point, target names have already been resolved. */
7577 /***********************************************************/
7578
7579 /* Check multi-process mode compatibility */
7580
7581 if (global.nbproc > 1 && global.stats_fe) {
7582 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7583 unsigned long mask;
7584
7585 mask = nbits(global.nbproc);
7586 if (global.stats_fe->bind_proc)
7587 mask &= global.stats_fe->bind_proc;
7588
7589 if (bind_conf->bind_proc)
7590 mask &= bind_conf->bind_proc;
7591
7592 /* stop here if more than one process is used */
7593 if (popcount(mask) > 1)
7594 break;
7595 }
7596 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7597 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");
7598 }
7599 }
7600
7601 /* Make each frontend inherit bind-process from its listeners when not specified. */
7602 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7603 if (curproxy->bind_proc)
7604 continue;
7605
7606 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7607 unsigned long mask;
7608
7609 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7610 curproxy->bind_proc |= mask;
7611 }
7612
7613 if (!curproxy->bind_proc)
7614 curproxy->bind_proc = ~0UL;
7615 }
7616
7617 if (global.stats_fe) {
7618 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7619 unsigned long mask;
7620
7621 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7622 global.stats_fe->bind_proc |= mask;
7623 }
7624 if (!global.stats_fe->bind_proc)
7625 global.stats_fe->bind_proc = ~0UL;
7626 }
7627
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007628 /* propagate bindings from frontends to backends. Don't do it if there
7629 * are any fatal errors as we must not call it with unresolved proxies.
7630 */
7631 if (!cfgerr) {
7632 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7633 if (curproxy->cap & PR_CAP_FE)
7634 propagate_processes(curproxy, NULL);
7635 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007636 }
7637
7638 /* Bind each unbound backend to all processes when not specified. */
7639 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7640 if (curproxy->bind_proc)
7641 continue;
7642 curproxy->bind_proc = ~0UL;
7643 }
7644
7645 /*******************************************************/
7646 /* At this step, all proxies have a non-null bind_proc */
7647 /*******************************************************/
7648
7649 /* perform the final checks before creating tasks */
7650
7651 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7652 struct listener *listener;
7653 unsigned int next_id;
7654 int nbproc;
7655
7656 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007657
Emeric Brunc52962f2012-11-15 18:28:02 +01007658#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007659 /* Configure SSL for each bind line.
7660 * Note: if configuration fails at some point, the ->ctx member
7661 * remains NULL so that listeners can later detach.
7662 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007663 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007664 int alloc_ctx;
7665
Emeric Brunc52962f2012-11-15 18:28:02 +01007666 if (!bind_conf->is_ssl) {
7667 if (bind_conf->default_ctx) {
7668 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7669 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7670 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007671 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007672 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007673 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007674 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007675 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007676 cfgerr++;
7677 continue;
7678 }
7679
Emeric Brun8dc60392014-05-09 13:52:00 +02007680 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007681 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007682 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7683 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");
7684 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007685 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007686 cfgerr++;
7687 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007688 }
7689
Emeric Brunfc0421f2012-09-07 17:30:07 +02007690 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007691 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007692 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007693#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007694
Willy Tarreaue6b98942007-10-29 01:09:36 +01007695 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007696 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007697 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007698 if (!listener->luid) {
7699 /* listener ID not set, use automatic numbering with first
7700 * spare entry starting with next_luid.
7701 */
7702 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7703 listener->conf.id.key = listener->luid = next_id;
7704 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007705 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007706 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007707
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007708 /* enable separate counters */
7709 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7710 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007711 if (!listener->name)
7712 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007713 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007714
Willy Tarreaue6b98942007-10-29 01:09:36 +01007715 if (curproxy->options & PR_O_TCP_NOLING)
7716 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007717 if (!listener->maxconn)
7718 listener->maxconn = curproxy->maxconn;
7719 if (!listener->backlog)
7720 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007721 if (!listener->maxaccept)
7722 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7723
7724 /* we want to have an optimal behaviour on single process mode to
7725 * maximize the work at once, but in multi-process we want to keep
7726 * some fairness between processes, so we target half of the max
7727 * number of events to be balanced over all the processes the proxy
7728 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7729 * used to disable the limit.
7730 */
7731 if (listener->maxaccept > 0) {
7732 if (nbproc > 1)
7733 listener->maxaccept = (listener->maxaccept + 1) / 2;
7734 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7735 }
7736
Willy Tarreau9903f0e2015-04-04 18:50:31 +02007737 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02007738 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007739 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01007740 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007741
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007742 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7743 listener->options |= LI_O_TCP_RULES;
7744
Willy Tarreaude3041d2010-05-31 10:56:17 +02007745 if (curproxy->mon_mask.s_addr)
7746 listener->options |= LI_O_CHK_MONNET;
7747
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007748 /* smart accept mode is automatic in HTTP mode */
7749 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007750 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007751 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7752 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007753 }
7754
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007755 /* Release unused SSL configs */
7756 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7757 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007758 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007759#ifdef USE_OPENSSL
7760 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007761 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007762 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007763 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007764 free(bind_conf->crl_file);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007765 free(bind_conf->tls_ticket_keys);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007766#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007767 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007768
Willy Tarreau102df612014-05-07 23:56:38 +02007769 if (nbproc > 1) {
7770 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02007771 int count, maxproc = 0;
7772
7773 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7774 count = popcount(bind_conf->bind_proc);
7775 if (count > maxproc)
7776 maxproc = count;
7777 }
7778 /* backends have 0, frontends have 1 or more */
7779 if (maxproc != 1)
7780 Warning("Proxy '%s': in multi-process mode, stats will be"
7781 " limited to process assigned to the current request.\n",
7782 curproxy->id);
7783
Willy Tarreau102df612014-05-07 23:56:38 +02007784 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7785 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7786 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007787 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007788 }
Willy Tarreau102df612014-05-07 23:56:38 +02007789 if (curproxy->appsession_name) {
7790 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7791 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007792 }
Willy Tarreau102df612014-05-07 23:56:38 +02007793 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7794 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7795 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007796 }
7797 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007798
7799 /* create the task associated with the proxy */
7800 curproxy->task = task_new();
7801 if (curproxy->task) {
7802 curproxy->task->context = curproxy;
7803 curproxy->task->process = manage_proxy;
7804 /* no need to queue, it will be done automatically if some
7805 * listener gets limited.
7806 */
7807 curproxy->task->expire = TICK_ETERNITY;
7808 } else {
7809 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7810 curproxy->id);
7811 cfgerr++;
7812 }
Willy Tarreaub369a042014-09-16 13:21:03 +02007813 }
7814
Willy Tarreaufbb78422011-06-05 15:38:35 +02007815 /* automatically compute fullconn if not set. We must not do it in the
7816 * loop above because cross-references are not yet fully resolved.
7817 */
7818 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7819 /* If <fullconn> is not set, let's set it to 10% of the sum of
7820 * the possible incoming frontend's maxconns.
7821 */
7822 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7823 struct proxy *fe;
7824 int total = 0;
7825
7826 /* sum up the number of maxconns of frontends which
7827 * reference this backend at least once or which are
7828 * the same one ('listen').
7829 */
7830 for (fe = proxy; fe; fe = fe->next) {
7831 struct switching_rule *rule;
7832 struct hdr_exp *exp;
7833 int found = 0;
7834
7835 if (!(fe->cap & PR_CAP_FE))
7836 continue;
7837
7838 if (fe == curproxy) /* we're on a "listen" instance */
7839 found = 1;
7840
7841 if (fe->defbe.be == curproxy) /* "default_backend" */
7842 found = 1;
7843
7844 /* check if a "use_backend" rule matches */
7845 if (!found) {
7846 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007847 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007848 found = 1;
7849 break;
7850 }
7851 }
7852 }
7853
7854 /* check if a "reqsetbe" rule matches */
7855 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7856 if (exp->action == ACT_SETBE &&
7857 (struct proxy *)exp->replace == curproxy) {
7858 found = 1;
7859 break;
7860 }
7861 }
7862
7863 /* now we've checked all possible ways to reference a backend
7864 * from a frontend.
7865 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007866 if (!found)
7867 continue;
7868 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007869 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007870 /* we have the sum of the maxconns in <total>. We only
7871 * keep 10% of that sum to set the default fullconn, with
7872 * a hard minimum of 1 (to avoid a divide by zero).
7873 */
7874 curproxy->fullconn = (total + 9) / 10;
7875 if (!curproxy->fullconn)
7876 curproxy->fullconn = 1;
7877 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007878 }
7879
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007880 /*
7881 * Recount currently required checks.
7882 */
7883
7884 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7885 int optnum;
7886
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007887 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7888 if (curproxy->options & cfg_opts[optnum].val)
7889 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007890
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007891 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7892 if (curproxy->options2 & cfg_opts2[optnum].val)
7893 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007894 }
7895
Willy Tarreau0fca4832015-05-01 19:12:05 +02007896 /* compute the required process bindings for the peers */
7897 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
7898 if (curproxy->table.peers.p)
7899 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
7900
Willy Tarreau122541c2011-09-07 21:24:49 +02007901 if (peers) {
7902 struct peers *curpeers = peers, **last;
7903 struct peer *p, *pb;
7904
Willy Tarreau1e273012015-05-01 19:15:17 +02007905 /* Remove all peers sections which don't have a valid listener,
7906 * which are not used by any table, or which are bound to more
7907 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02007908 */
7909 last = &peers;
7910 while (*last) {
7911 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007912
7913 if (curpeers->state == PR_STSTOPPED) {
7914 /* the "disabled" keyword was present */
7915 if (curpeers->peers_fe)
7916 stop_proxy(curpeers->peers_fe);
7917 curpeers->peers_fe = NULL;
7918 }
7919 else if (!curpeers->peers_fe) {
7920 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7921 curpeers->id, localpeer);
7922 }
Willy Tarreau1e273012015-05-01 19:15:17 +02007923 else if (popcount(curpeers->peers_fe->bind_proc) != 1) {
7924 /* either it's totally stopped or too much used */
7925 if (curpeers->peers_fe->bind_proc) {
7926 Alert("Peers section '%s': peers referenced by sections "
7927 "running in different processes. Check global.nbproc"
Willy Tarreau0334ffc2015-05-04 21:46:08 +02007928 " and all tables' bind-process settings.\n",
Willy Tarreau1e273012015-05-01 19:15:17 +02007929 curpeers->id);
7930 cfgerr++;
7931 }
7932 stop_proxy(curpeers->peers_fe);
7933 curpeers->peers_fe = NULL;
7934 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007935 else {
Willy Tarreau122541c2011-09-07 21:24:49 +02007936 last = &curpeers->next;
7937 continue;
7938 }
7939
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007940 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02007941 p = curpeers->remote;
7942 while (p) {
7943 pb = p->next;
7944 free(p->id);
7945 free(p);
7946 p = pb;
7947 }
7948
7949 /* Destroy and unlink this curpeers section.
7950 * Note: curpeers is backed up into *last.
7951 */
7952 free(curpeers->id);
7953 curpeers = curpeers->next;
7954 free(*last);
7955 *last = curpeers;
7956 }
7957 }
7958
Willy Tarreau6866f3f2015-05-01 19:09:08 +02007959 /* initialize stick-tables on backend capable proxies. This must not
7960 * be done earlier because the data size may be discovered while parsing
7961 * other proxies.
7962 */
7963 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7964 if (curproxy->state == PR_STSTOPPED)
7965 continue;
7966
7967 if (!stktable_init(&curproxy->table)) {
7968 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7969 cfgerr++;
7970 }
7971 }
7972
Simon Horman0d16a402015-01-30 11:22:58 +09007973 if (mailers) {
7974 struct mailers *curmailers = mailers, **last;
7975 struct mailer *m, *mb;
7976
7977 /* Remove all mailers sections which don't have a valid listener.
7978 * This can happen when a mailers section is never referenced.
7979 */
7980 last = &mailers;
7981 while (*last) {
7982 curmailers = *last;
7983 if (curmailers->users) {
7984 last = &curmailers->next;
7985 continue;
7986 }
7987
7988 Warning("Removing incomplete section 'mailers %s'.\n",
7989 curmailers->id);
7990
7991 m = curmailers->mailer_list;
7992 while (m) {
7993 mb = m->next;
7994 free(m->id);
7995 free(m);
7996 m = mb;
7997 }
7998
7999 /* Destroy and unlink this curmailers section.
8000 * Note: curmailers is backed up into *last.
8001 */
8002 free(curmailers->id);
8003 curmailers = curmailers->next;
8004 free(*last);
8005 *last = curmailers;
8006 }
8007 }
8008
Willy Tarreau34eb6712011-10-24 18:15:04 +02008009 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008010 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008011 MEM_F_SHARED);
8012
Willy Tarreaubb925012009-07-23 13:36:36 +02008013 if (cfgerr > 0)
8014 err_code |= ERR_ALERT | ERR_FATAL;
8015 out:
8016 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008017}
8018
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008019/*
8020 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8021 * parsing sessions.
8022 */
8023void cfg_register_keywords(struct cfg_kw_list *kwl)
8024{
8025 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8026}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008027
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008028/*
8029 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8030 */
8031void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8032{
8033 LIST_DEL(&kwl->list);
8034 LIST_INIT(&kwl->list);
8035}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008036
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008037/* this function register new section in the haproxy configuration file.
8038 * <section_name> is the name of this new section and <section_parser>
8039 * is the called parser. If two section declaration have the same name,
8040 * only the first declared is used.
8041 */
8042int cfg_register_section(char *section_name,
8043 int (*section_parser)(const char *, int, char **, int))
8044{
8045 struct cfg_section *cs;
8046
8047 cs = calloc(1, sizeof(*cs));
8048 if (!cs) {
8049 Alert("register section '%s': out of memory.\n", section_name);
8050 return 0;
8051 }
8052
8053 cs->section_name = section_name;
8054 cs->section_parser = section_parser;
8055
8056 LIST_ADDQ(&sections, &cs->list);
8057
8058 return 1;
8059}
8060
Willy Tarreaubaaee002006-06-26 02:48:02 +02008061/*
8062 * Local variables:
8063 * c-indent-level: 8
8064 * c-basic-offset: 8
8065 * End:
8066 */