blob: c55a56161fc31d2a11176ebb08271959734770dc [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>
Christopher Fauletd7c91962015-04-30 11:48:27 +020048#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010050#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020051#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090052#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020053#include <types/dns.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020054
Willy Tarreaueb0c6142007-05-07 00:53:22 +020055#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010056#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020058#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020059#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020060#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020061#include <proto/dumpstats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020062#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020063#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020064#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020065#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010066#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020067#include <proto/lb_fwlc.h>
68#include <proto/lb_fwrr.h>
69#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020070#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020071#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020072#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010073#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020074#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010075#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010076#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020077#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020078#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020079#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020080#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020081#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020082#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020083#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010084#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020085
Emeric Brunfc0421f2012-09-07 17:30:07 +020086#ifdef USE_OPENSSL
87#include <types/ssl_sock.h>
88#include <proto/ssl_sock.h>
89#include <proto/shctx.h>
90#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020091
Willy Tarreauf3c69202006-07-09 16:42:34 +020092/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
93 * ssl-hello-chk option to ensure that the remote server speaks SSL.
94 *
95 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
96 */
97const char sslv3_client_hello_pkt[] = {
98 "\x16" /* ContentType : 0x16 = Hanshake */
99 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
100 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
101 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
102 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
103 "\x03\x00" /* Hello Version : 0x0300 = v3 */
104 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
105 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
106 "\x00" /* Session ID length : empty (no session ID) */
107 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
108 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
109 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
110 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
111 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
112 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
113 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
114 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
115 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
116 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
117 "\x00\x38" "\x00\x39" "\x00\x3A"
118 "\x01" /* Compression Length : 0x01 = 1 byte for types */
119 "\x00" /* Compression Type : 0x00 = NULL compression */
120};
121
Willy Tarreau3842f002009-06-14 11:39:52 +0200122/* various keyword modifiers */
123enum kw_mod {
124 KWM_STD = 0, /* normal */
125 KWM_NO, /* "no" prefixed before the keyword */
126 KWM_DEF, /* "default" prefixed before the keyword */
127};
128
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100129/* permit to store configuration section */
130struct cfg_section {
131 struct list list;
132 char *section_name;
133 int (*section_parser)(const char *, int, char **, int);
134};
135
136/* Used to chain configuration sections definitions. This list
137 * stores struct cfg_section
138 */
139struct list sections = LIST_HEAD_INIT(sections);
140
Willy Tarreau13943ab2006-12-31 00:24:10 +0100141/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100143 const char *name;
144 unsigned int val;
145 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100146 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148};
149
150/* proxy->options */
151static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100152{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
154 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
155 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
156 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
157 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
158 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100159 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200160 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200161 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100162 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
164 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
165 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100166 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100167#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100168 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100169#else
170 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100171#endif
172
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100174};
175
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176/* proxy->options2 */
177static const struct cfg_opt cfg_opts2[] =
178{
179#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100180 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
181 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
182 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100183#else
184 { "splice-request", 0, 0, 0, 0 },
185 { "splice-response", 0, 0, 0, 0 },
186 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100187#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100188 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
189 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
190 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
191 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
192 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
193 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
194 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
195 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
196 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400197 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100198 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200199 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200200 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100201 { NULL, 0, 0, 0 }
202};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203
Willy Tarreau6daf3432008-01-22 16:44:08 +0100204static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
206int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100207int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200209/* List head of all known configuration keywords */
210static struct cfg_kw_list cfg_keywords = {
211 .list = LIST_HEAD_INIT(cfg_keywords.list)
212};
213
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214/*
215 * converts <str> to a list of listeners which are dynamically allocated.
216 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
217 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
218 * - <port> is a numerical port from 1 to 65535 ;
219 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
220 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200221 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
222 * not NULL, it must be a valid pointer to either NULL or a freeable area that
223 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200225int 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 +0200226{
227 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100228 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229 int port, end;
230
231 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200232
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100234 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100235 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236
237 str = next;
238 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100239 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240 *next++ = 0;
241 }
242
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100243 ss2 = str2sa_range(str, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200244 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200245 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100246 if (!ss2)
247 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200248
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100249 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100250 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200251 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100252 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200253 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100255 if (!port || !end) {
256 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
257 goto fail;
258 }
259
Emeric Bruned760922010-10-22 17:59:25 +0200260 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200261 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200262 goto fail;
263 }
264
265 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200266 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200267 goto fail;
268 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200269 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100270 else if (ss2->ss_family == AF_UNSPEC) {
271 socklen_t addr_len;
272
273 /* We want to attach to an already bound fd whose number
274 * is in the addr part of ss2 when cast to sockaddr_in.
275 * Note that by definition there is a single listener.
276 * We still have to determine the address family to
277 * register the correct protocol.
278 */
279 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
280 addr_len = sizeof(*ss2);
281 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
282 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
283 goto fail;
284 }
285
286 port = end = get_host_port(ss2);
287 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100289 /* OK the address looks correct */
290 ss = *ss2;
291
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292 for (; port <= end; port++) {
293 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100294 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200295 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
296 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
297 l->frontend = curproxy;
298 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299
Willy Tarreau40aa0702013-03-10 23:51:38 +0100300 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200302 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100303 l->state = LI_INIT;
304
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100305 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200306 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100307 tcpv4_add_listener(l);
308 }
Emeric Bruned760922010-10-22 17:59:25 +0200309 else if (ss.ss_family == AF_INET6) {
310 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
311 tcpv6_add_listener(l);
312 }
313 else {
Emeric Bruned760922010-10-22 17:59:25 +0200314 uxst_add_listener(l);
315 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200316
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200317 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100318 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319 } /* end for(port) */
320 } /* end while(next) */
321 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200322 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200323 fail:
324 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200325 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200326}
327
William Lallemand6e62fb62015-04-28 16:55:23 +0200328/*
329 * Report a fatal Alert when there is too much arguments
330 * The index is the current keyword in args
331 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
332 * Fill err_code with an ERR_ALERT and an ERR_FATAL
333 */
334int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
335{
336 char *kw = NULL;
337 int i;
338
339 if (!*args[index + maxarg + 1])
340 return 0;
341
342 memprintf(&kw, "%s", args[0]);
343 for (i = 1; i <= index; i++) {
344 memprintf(&kw, "%s %s", kw, args[i]);
345 }
346
347 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
348 free(kw);
349 *err_code |= ERR_ALERT | ERR_FATAL;
350 return 1;
351}
352
353/*
354 * same as alertif_too_many_args_idx with a 0 index
355 */
356int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
357{
358 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
359}
360
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200361/* Report a warning if a rule is placed after a 'tcp-request content' rule.
362 * Return 1 if the warning has been emitted, otherwise 0.
363 */
364int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
365{
366 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
367 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
368 file, line, arg);
369 return 1;
370 }
371 return 0;
372}
373
Willy Tarreau61d18892009-03-31 10:49:21 +0200374/* Report a warning if a rule is placed after a 'block' rule.
375 * Return 1 if the warning has been emitted, otherwise 0.
376 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100377int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200378{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200379 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200380 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
381 file, line, arg);
382 return 1;
383 }
384 return 0;
385}
386
Willy Tarreau5002f572014-04-23 01:32:02 +0200387/* Report a warning if a rule is placed after an 'http_request' rule.
388 * Return 1 if the warning has been emitted, otherwise 0.
389 */
390int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
391{
392 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
393 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
394 file, line, arg);
395 return 1;
396 }
397 return 0;
398}
399
Willy Tarreau61d18892009-03-31 10:49:21 +0200400/* Report a warning if a rule is placed after a reqrewrite rule.
401 * Return 1 if the warning has been emitted, otherwise 0.
402 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 if (proxy->req_exp) {
406 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
407 file, line, arg);
408 return 1;
409 }
410 return 0;
411}
412
413/* Report a warning if a rule is placed after a reqadd rule.
414 * Return 1 if the warning has been emitted, otherwise 0.
415 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100416int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200417{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100418 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200419 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
420 file, line, arg);
421 return 1;
422 }
423 return 0;
424}
425
426/* Report a warning if a rule is placed after a redirect rule.
427 * Return 1 if the warning has been emitted, otherwise 0.
428 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100429int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200430{
431 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
432 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
433 file, line, arg);
434 return 1;
435 }
436 return 0;
437}
438
439/* Report a warning if a rule is placed after a 'use_backend' rule.
440 * Return 1 if the warning has been emitted, otherwise 0.
441 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100442int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200443{
444 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
445 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
446 file, line, arg);
447 return 1;
448 }
449 return 0;
450}
451
Willy Tarreauee445d92014-04-23 01:39:04 +0200452/* Report a warning if a rule is placed after a 'use-server' rule.
453 * Return 1 if the warning has been emitted, otherwise 0.
454 */
455int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
456{
457 if (!LIST_ISEMPTY(&proxy->server_rules)) {
458 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
459 file, line, arg);
460 return 1;
461 }
462 return 0;
463}
464
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200465/* report a warning if a "tcp request connection" rule is dangerously placed */
466int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
467{
468 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
469 warnif_rule_after_block(proxy, file, line, arg) ||
470 warnif_rule_after_http_req(proxy, file, line, arg) ||
471 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
472 warnif_rule_after_reqadd(proxy, file, line, arg) ||
473 warnif_rule_after_redirect(proxy, file, line, arg) ||
474 warnif_rule_after_use_backend(proxy, file, line, arg) ||
475 warnif_rule_after_use_server(proxy, file, line, arg);
476}
477
478/* report a warning if a "tcp request content" rule is dangerously placed */
479int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
480{
481 return warnif_rule_after_block(proxy, file, line, arg) ||
482 warnif_rule_after_http_req(proxy, file, line, arg) ||
483 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
484 warnif_rule_after_reqadd(proxy, file, line, arg) ||
485 warnif_rule_after_redirect(proxy, file, line, arg) ||
486 warnif_rule_after_use_backend(proxy, file, line, arg) ||
487 warnif_rule_after_use_server(proxy, file, line, arg);
488}
489
Willy Tarreau61d18892009-03-31 10:49:21 +0200490/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100491int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200492{
Willy Tarreau5002f572014-04-23 01:32:02 +0200493 return warnif_rule_after_http_req(proxy, file, line, arg) ||
494 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
495 warnif_rule_after_reqadd(proxy, file, line, arg) ||
496 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200497 warnif_rule_after_use_backend(proxy, file, line, arg) ||
498 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200499}
500
501/* report a warning if an http-request rule is dangerously placed */
502int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
503{
Willy Tarreau61d18892009-03-31 10:49:21 +0200504 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
505 warnif_rule_after_reqadd(proxy, file, line, arg) ||
506 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200507 warnif_rule_after_use_backend(proxy, file, line, arg) ||
508 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200509}
510
511/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100512int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200513{
514 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
515 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200516 warnif_rule_after_use_backend(proxy, file, line, arg) ||
517 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200518}
519
520/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100521int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200522{
523 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200524 warnif_rule_after_use_backend(proxy, file, line, arg) ||
525 warnif_rule_after_use_server(proxy, file, line, arg);
526}
527
528/* report a warning if a redirect rule is dangerously placed */
529int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
530{
531 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
532 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200533}
534
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100535/* Report it if a request ACL condition uses some keywords that are incompatible
536 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
537 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
538 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100539 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100540static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100541{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100542 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200543 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100544
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100545 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100546 return 0;
547
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100548 acl = acl_cond_conflicts(cond, where);
549 if (acl) {
550 if (acl->name && *acl->name)
551 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
552 file, line, acl->name, sample_ckp_names(where));
553 else
554 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 +0200555 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100556 return ERR_WARN;
557 }
558 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100559 return 0;
560
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100561 if (acl->name && *acl->name)
562 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200563 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100564 else
565 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200566 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100567 return ERR_WARN;
568}
569
Willy Tarreaubaaee002006-06-26 02:48:02 +0200570/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200571 * parse a line in a <global> section. Returns the error code, 0 if OK, or
572 * any combination of :
573 * - ERR_ABORT: must abort ASAP
574 * - ERR_FATAL: we can continue parsing but not start the service
575 * - ERR_WARN: a warning has been emitted
576 * - ERR_ALERT: an alert has been emitted
577 * Only the two first ones can stop processing, the two others are just
578 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200580int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581{
Willy Tarreau058e9072009-07-20 09:30:05 +0200582 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200583 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200584
585 if (!strcmp(args[0], "global")) { /* new section */
586 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200587 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200590 else if (!strcmp(args[0], "ca-base")) {
591#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200592 if(alertif_too_many_args(1, file, linenum, args, &err_code))
593 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200594 if (global.ca_base != NULL) {
595 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
596 err_code |= ERR_ALERT;
597 goto out;
598 }
599 if (*(args[1]) == 0) {
600 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
601 err_code |= ERR_ALERT | ERR_FATAL;
602 goto out;
603 }
604 global.ca_base = strdup(args[1]);
605#else
606 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
607 err_code |= ERR_ALERT | ERR_FATAL;
608 goto out;
609#endif
610 }
611 else if (!strcmp(args[0], "crt-base")) {
612#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200613 if (alertif_too_many_args(1, file, linenum, args, &err_code))
614 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200615 if (global.crt_base != NULL) {
616 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
617 err_code |= ERR_ALERT;
618 goto out;
619 }
620 if (*(args[1]) == 0) {
621 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
622 err_code |= ERR_ALERT | ERR_FATAL;
623 goto out;
624 }
625 global.crt_base = strdup(args[1]);
626#else
627 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
628 err_code |= ERR_ALERT | ERR_FATAL;
629 goto out;
630#endif
631 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200632 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200633 if (alertif_too_many_args(0, file, linenum, args, &err_code))
634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 global.mode |= MODE_DAEMON;
636 }
637 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200638 if (alertif_too_many_args(0, file, linenum, args, &err_code))
639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200640 global.mode |= MODE_DEBUG;
641 }
642 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200643 if (alertif_too_many_args(0, file, linenum, args, &err_code))
644 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100645 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200646 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200647 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200648 if (alertif_too_many_args(0, file, linenum, args, &err_code))
649 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100650 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200651 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200653 if (alertif_too_many_args(0, file, linenum, args, &err_code))
654 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100655 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100657 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200658 if (alertif_too_many_args(0, file, linenum, args, &err_code))
659 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100660 global.tune.options &= ~GTUNE_USE_SPLICE;
661 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200662 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200663 if (alertif_too_many_args(0, file, linenum, args, &err_code))
664 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200665 global.tune.options &= ~GTUNE_USE_GAI;
666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200667 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200668 if (alertif_too_many_args(0, file, linenum, args, &err_code))
669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 global.mode |= MODE_QUIET;
671 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200672 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200673 if (alertif_too_many_args(1, file, linenum, args, &err_code))
674 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200675 if (global.tune.maxpollevents != 0) {
676 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT;
678 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200679 }
680 if (*(args[1]) == 0) {
681 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200682 err_code |= ERR_ALERT | ERR_FATAL;
683 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200684 }
685 global.tune.maxpollevents = atol(args[1]);
686 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100687 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200688 if (alertif_too_many_args(1, file, linenum, args, &err_code))
689 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100690 if (global.tune.maxaccept != 0) {
691 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT;
693 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100694 }
695 if (*(args[1]) == 0) {
696 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200697 err_code |= ERR_ALERT | ERR_FATAL;
698 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100699 }
700 global.tune.maxaccept = atol(args[1]);
701 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200702 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200703 if (alertif_too_many_args(1, file, linenum, args, &err_code))
704 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200705 if (*(args[1]) == 0) {
706 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
707 err_code |= ERR_ALERT | ERR_FATAL;
708 goto out;
709 }
710 global.tune.chksize = atol(args[1]);
711 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100712 else if (!strcmp(args[0], "tune.recv_enough")) {
713 if (alertif_too_many_args(1, file, linenum, args, &err_code))
714 goto out;
715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 global.tune.recv_enough = atol(args[1]);
721 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200722#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200723 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200724 if (alertif_too_many_args(0, file, linenum, args, &err_code))
725 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200726 global.tune.sslprivatecache = 1;
727 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100728 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200729 if (alertif_too_many_args(1, file, linenum, args, &err_code))
730 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200731 if (*(args[1]) == 0) {
732 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
733 err_code |= ERR_ALERT | ERR_FATAL;
734 goto out;
735 }
736 global.tune.sslcachesize = atol(args[1]);
737 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100738 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
739 unsigned int ssllifetime;
740 const char *res;
741
William Lallemand1a748ae2015-05-19 16:37:23 +0200742 if (alertif_too_many_args(1, file, linenum, args, &err_code))
743 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100744 if (*(args[1]) == 0) {
745 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
746 err_code |= ERR_ALERT | ERR_FATAL;
747 goto out;
748 }
749
750 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
751 if (res) {
752 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
753 file, linenum, *res, args[0]);
754 err_code |= ERR_ALERT | ERR_FATAL;
755 goto out;
756 }
757
758 global.tune.ssllifetime = ssllifetime;
759 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100760 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200761 if (alertif_too_many_args(1, file, linenum, args, &err_code))
762 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100763 if (*(args[1]) == 0) {
764 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
765 err_code |= ERR_ALERT | ERR_FATAL;
766 goto out;
767 }
768 global.tune.ssl_max_record = atol(args[1]);
769 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200770#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200771 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200772 if (alertif_too_many_args(1, file, linenum, args, &err_code))
773 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200774 if (*(args[1]) == 0) {
775 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
776 err_code |= ERR_ALERT | ERR_FATAL;
777 goto out;
778 }
779 global.tune.ssl_default_dh_param = atol(args[1]);
780 if (global.tune.ssl_default_dh_param < 1024) {
781 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
782 err_code |= ERR_ALERT | ERR_FATAL;
783 goto out;
784 }
785 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200786#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200787 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
788 if (alertif_too_many_args(1, file, linenum, args, &err_code))
789 goto out;
790 if (*(args[1]) == 0) {
791 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
794 }
795 global.tune.ssl_ctx_cache = atoi(args[1]);
796 if (global.tune.ssl_ctx_cache < 0) {
797 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
798 file, linenum, args[0]);
799 err_code |= ERR_ALERT | ERR_FATAL;
800 goto out;
801 }
802 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200803#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100804 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200805 if (alertif_too_many_args(1, file, linenum, args, &err_code))
806 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
811 }
812 global.tune.buf_limit = atol(args[1]);
813 if (global.tune.buf_limit) {
814 if (global.tune.buf_limit < 3)
815 global.tune.buf_limit = 3;
816 if (global.tune.buf_limit <= global.tune.reserved_bufs)
817 global.tune.buf_limit = global.tune.reserved_bufs + 1;
818 }
819 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100820 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200821 if (alertif_too_many_args(1, file, linenum, args, &err_code))
822 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100823 if (*(args[1]) == 0) {
824 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
827 }
828 global.tune.reserved_bufs = atol(args[1]);
829 if (global.tune.reserved_bufs < 2)
830 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100831 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
832 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100833 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200834 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200835 if (alertif_too_many_args(1, file, linenum, args, &err_code))
836 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200837 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.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200843 if (global.tune.bufsize <= 0) {
844 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
845 err_code |= ERR_ALERT | ERR_FATAL;
846 goto out;
847 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100848 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100849 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200850 }
851 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200852 if (alertif_too_many_args(1, file, linenum, args, &err_code))
853 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200854 if (*(args[1]) == 0) {
855 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200860 if (global.tune.maxrewrite < 0) {
861 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200865 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100866 else if (!strcmp(args[0], "tune.idletimer")) {
867 unsigned int idle;
868 const char *res;
869
William Lallemand1a748ae2015-05-19 16:37:23 +0200870 if (alertif_too_many_args(1, file, linenum, args, &err_code))
871 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100872 if (*(args[1]) == 0) {
873 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
874 err_code |= ERR_ALERT | ERR_FATAL;
875 goto out;
876 }
877
878 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
879 if (res) {
880 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
881 file, linenum, *res, args[0]);
882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
884 }
885
886 if (idle > 65535) {
887 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
888 err_code |= ERR_ALERT | ERR_FATAL;
889 goto out;
890 }
891 global.tune.idle_timer = idle;
892 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100893 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200894 if (alertif_too_many_args(1, file, linenum, args, &err_code))
895 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100896 if (global.tune.client_rcvbuf != 0) {
897 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
898 err_code |= ERR_ALERT;
899 goto out;
900 }
901 if (*(args[1]) == 0) {
902 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
903 err_code |= ERR_ALERT | ERR_FATAL;
904 goto out;
905 }
906 global.tune.client_rcvbuf = atol(args[1]);
907 }
908 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200909 if (alertif_too_many_args(1, file, linenum, args, &err_code))
910 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100911 if (global.tune.server_rcvbuf != 0) {
912 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
913 err_code |= ERR_ALERT;
914 goto out;
915 }
916 if (*(args[1]) == 0) {
917 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
918 err_code |= ERR_ALERT | ERR_FATAL;
919 goto out;
920 }
921 global.tune.server_rcvbuf = atol(args[1]);
922 }
923 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200924 if (alertif_too_many_args(1, file, linenum, args, &err_code))
925 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100926 if (global.tune.client_sndbuf != 0) {
927 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
928 err_code |= ERR_ALERT;
929 goto out;
930 }
931 if (*(args[1]) == 0) {
932 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
935 }
936 global.tune.client_sndbuf = atol(args[1]);
937 }
938 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200939 if (alertif_too_many_args(1, file, linenum, args, &err_code))
940 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100941 if (global.tune.server_sndbuf != 0) {
942 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
943 err_code |= ERR_ALERT;
944 goto out;
945 }
946 if (*(args[1]) == 0) {
947 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
948 err_code |= ERR_ALERT | ERR_FATAL;
949 goto out;
950 }
951 global.tune.server_sndbuf = atol(args[1]);
952 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200953 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200954 if (alertif_too_many_args(1, file, linenum, args, &err_code))
955 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200956 if (*(args[1]) == 0) {
957 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
958 err_code |= ERR_ALERT | ERR_FATAL;
959 goto out;
960 }
961 global.tune.pipesize = atol(args[1]);
962 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100963 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200964 if (alertif_too_many_args(1, file, linenum, args, &err_code))
965 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100966 if (*(args[1]) == 0) {
967 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
968 err_code |= ERR_ALERT | ERR_FATAL;
969 goto out;
970 }
971 global.tune.cookie_len = atol(args[1]) + 1;
972 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200973 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200974 if (alertif_too_many_args(1, file, linenum, args, &err_code))
975 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200976 if (*(args[1]) == 0) {
977 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
978 err_code |= ERR_ALERT | ERR_FATAL;
979 goto out;
980 }
981 global.tune.max_http_hdr = atol(args[1]);
982 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100983 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
984#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200985 if (alertif_too_many_args(1, file, linenum, args, &err_code))
986 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100987 if (*args[1]) {
988 global.tune.zlibmemlevel = atoi(args[1]);
989 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
990 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
991 file, linenum, args[0]);
992 err_code |= ERR_ALERT | ERR_FATAL;
993 goto out;
994 }
995 } else {
996 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
997 file, linenum, args[0]);
998 err_code |= ERR_ALERT | ERR_FATAL;
999 goto out;
1000 }
1001#else
1002 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005#endif
1006 }
1007 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
1008#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001009 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1010 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001011 if (*args[1]) {
1012 global.tune.zlibwindowsize = atoi(args[1]);
1013 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
1014 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1015 file, linenum, args[0]);
1016 err_code |= ERR_ALERT | ERR_FATAL;
1017 goto out;
1018 }
1019 } else {
1020 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1021 file, linenum, args[0]);
1022 err_code |= ERR_ALERT | ERR_FATAL;
1023 goto out;
1024 }
1025#else
1026 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1027 err_code |= ERR_ALERT | ERR_FATAL;
1028 goto out;
1029#endif
1030 }
William Lallemandf3747832012-11-09 12:33:10 +01001031 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001032 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1033 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001034 if (*args[1]) {
1035 global.tune.comp_maxlevel = atoi(args[1]);
1036 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1037 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1038 file, linenum, args[0]);
1039 err_code |= ERR_ALERT | ERR_FATAL;
1040 goto out;
1041 }
1042 } else {
1043 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1044 file, linenum, args[0]);
1045 err_code |= ERR_ALERT | ERR_FATAL;
1046 goto out;
1047 }
1048 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001049 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1050 if (*args[1]) {
1051 global.tune.pattern_cache = atoi(args[1]);
1052 if (global.tune.pattern_cache < 0) {
1053 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1054 file, linenum, args[0]);
1055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
1057 }
1058 } else {
1059 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1060 file, linenum, args[0]);
1061 err_code |= ERR_ALERT | ERR_FATAL;
1062 goto out;
1063 }
1064 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001066 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001069 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001070 err_code |= ERR_ALERT;
1071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 }
1073 if (*(args[1]) == 0) {
1074 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001075 err_code |= ERR_ALERT | ERR_FATAL;
1076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001077 }
1078 global.uid = atol(args[1]);
1079 }
1080 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001081 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001083 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001084 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001085 err_code |= ERR_ALERT;
1086 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 }
1088 if (*(args[1]) == 0) {
1089 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT | ERR_FATAL;
1091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 }
1093 global.gid = atol(args[1]);
1094 }
Simon Horman98637e52014-06-20 12:30:16 +09001095 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001096 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1097 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001098 global.external_check = 1;
1099 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001100 /* user/group name handling */
1101 else if (!strcmp(args[0], "user")) {
1102 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001103 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1104 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001105 if (global.uid != 0) {
1106 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001107 err_code |= ERR_ALERT;
1108 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001109 }
1110 errno = 0;
1111 ha_user = getpwnam(args[1]);
1112 if (ha_user != NULL) {
1113 global.uid = (int)ha_user->pw_uid;
1114 }
1115 else {
1116 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 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001118 }
1119 }
1120 else if (!strcmp(args[0], "group")) {
1121 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001122 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1123 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001124 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001125 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT;
1127 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001128 }
1129 errno = 0;
1130 ha_group = getgrnam(args[1]);
1131 if (ha_group != NULL) {
1132 global.gid = (int)ha_group->gr_gid;
1133 }
1134 else {
1135 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 +02001136 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001137 }
1138 }
1139 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001140 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001141 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143 if (*(args[1]) == 0) {
1144 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001145 err_code |= ERR_ALERT | ERR_FATAL;
1146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147 }
1148 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001149 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1150 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1151 file, linenum, args[0], LONGBITS, global.nbproc);
1152 err_code |= ERR_ALERT | ERR_FATAL;
1153 goto out;
1154 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001155 }
1156 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001157 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001159 if (global.maxconn != 0) {
1160 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001161 err_code |= ERR_ALERT;
1162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163 }
1164 if (*(args[1]) == 0) {
1165 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001166 err_code |= ERR_ALERT | ERR_FATAL;
1167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 }
1169 global.maxconn = atol(args[1]);
1170#ifdef SYSTEM_MAXCONN
1171 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1172 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);
1173 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001174 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001175 }
1176#endif /* SYSTEM_MAXCONN */
1177 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001178 else if (!strcmp(args[0], "maxsslconn")) {
1179#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001180 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1181 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001182 if (*(args[1]) == 0) {
1183 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 goto out;
1186 }
1187 global.maxsslconn = atol(args[1]);
1188#else
Emeric Brun0914df82012-10-02 18:45:42 +02001189 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1190 err_code |= ERR_ALERT | ERR_FATAL;
1191 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001192#endif
1193 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001194 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1195#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001196 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1197 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001198 if (*(args[1]) == 0) {
1199 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1200 err_code |= ERR_ALERT | ERR_FATAL;
1201 goto out;
1202 }
1203 free(global.listen_default_ciphers);
1204 global.listen_default_ciphers = strdup(args[1]);
1205#else
1206 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1207 err_code |= ERR_ALERT | ERR_FATAL;
1208 goto out;
1209#endif
1210 }
1211 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1212#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001213 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1214 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001215 if (*(args[1]) == 0) {
1216 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1217 err_code |= ERR_ALERT | ERR_FATAL;
1218 goto out;
1219 }
1220 free(global.connect_default_ciphers);
1221 global.connect_default_ciphers = strdup(args[1]);
1222#else
1223 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1224 err_code |= ERR_ALERT | ERR_FATAL;
1225 goto out;
1226#endif
1227 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001228#ifdef USE_OPENSSL
1229#ifndef OPENSSL_NO_DH
1230 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1231 if (*(args[1]) == 0) {
1232 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1233 err_code |= ERR_ALERT | ERR_FATAL;
1234 goto out;
1235 }
1236 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1237 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1238 err_code |= ERR_ALERT | ERR_FATAL;
1239 goto out;
1240 }
1241 }
1242#endif
1243#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001244 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001245 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1246 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001247 if (*(args[1]) == 0) {
1248 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
1251 }
1252 if (strcmp(args[1],"none") == 0)
1253 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1254 else if (strcmp(args[1],"required") == 0)
1255 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1256 else {
1257 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1258 err_code |= ERR_ALERT | ERR_FATAL;
1259 goto out;
1260 }
1261 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001262 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001263 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1264 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001265 if (global.cps_lim != 0) {
1266 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1267 err_code |= ERR_ALERT;
1268 goto out;
1269 }
1270 if (*(args[1]) == 0) {
1271 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1272 err_code |= ERR_ALERT | ERR_FATAL;
1273 goto out;
1274 }
1275 global.cps_lim = atol(args[1]);
1276 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001277 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001278 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1279 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001280 if (global.sps_lim != 0) {
1281 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1282 err_code |= ERR_ALERT;
1283 goto out;
1284 }
1285 if (*(args[1]) == 0) {
1286 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1287 err_code |= ERR_ALERT | ERR_FATAL;
1288 goto out;
1289 }
1290 global.sps_lim = atol(args[1]);
1291 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001292 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001293 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1294 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001295 if (global.ssl_lim != 0) {
1296 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1297 err_code |= ERR_ALERT;
1298 goto out;
1299 }
1300 if (*(args[1]) == 0) {
1301 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1302 err_code |= ERR_ALERT | ERR_FATAL;
1303 goto out;
1304 }
1305 global.ssl_lim = atol(args[1]);
1306 }
William Lallemandd85f9172012-11-09 17:05:39 +01001307 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001308 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1309 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001310 if (*(args[1]) == 0) {
1311 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1312 err_code |= ERR_ALERT | ERR_FATAL;
1313 goto out;
1314 }
1315 global.comp_rate_lim = atoi(args[1]) * 1024;
1316 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001317 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001318 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1319 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001320 if (global.maxpipes != 0) {
1321 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001322 err_code |= ERR_ALERT;
1323 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001324 }
1325 if (*(args[1]) == 0) {
1326 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001327 err_code |= ERR_ALERT | ERR_FATAL;
1328 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001329 }
1330 global.maxpipes = atol(args[1]);
1331 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001332 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001333 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1334 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001335 if (*(args[1]) == 0) {
1336 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1337 err_code |= ERR_ALERT | ERR_FATAL;
1338 goto out;
1339 }
William Lallemande3a7d992012-11-20 11:25:20 +01001340 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001341 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001342 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001343 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1344 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001345 if (*(args[1]) == 0) {
1346 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1347 err_code |= ERR_ALERT | ERR_FATAL;
1348 goto out;
1349 }
1350 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001351 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001352 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1353 err_code |= ERR_ALERT | ERR_FATAL;
1354 goto out;
1355 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001356 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001357
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001359 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001361 if (global.rlimit_nofile != 0) {
1362 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001363 err_code |= ERR_ALERT;
1364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001365 }
1366 if (*(args[1]) == 0) {
1367 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001368 err_code |= ERR_ALERT | ERR_FATAL;
1369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001370 }
1371 global.rlimit_nofile = atol(args[1]);
1372 }
1373 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001374 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 if (global.chroot != NULL) {
1377 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001378 err_code |= ERR_ALERT;
1379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380 }
1381 if (*(args[1]) == 0) {
1382 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001383 err_code |= ERR_ALERT | ERR_FATAL;
1384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 }
1386 global.chroot = strdup(args[1]);
1387 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001388 else if (!strcmp(args[0], "description")) {
1389 int i, len=0;
1390 char *d;
1391
1392 if (!*args[1]) {
1393 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1394 file, linenum, args[0]);
1395 err_code |= ERR_ALERT | ERR_FATAL;
1396 goto out;
1397 }
1398
Willy Tarreau348acfe2014-04-14 15:00:39 +02001399 for (i = 1; *args[i]; i++)
1400 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001401
1402 if (global.desc)
1403 free(global.desc);
1404
1405 global.desc = d = (char *)calloc(1, len);
1406
Willy Tarreau348acfe2014-04-14 15:00:39 +02001407 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1408 for (i = 2; *args[i]; i++)
1409 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001410 }
1411 else if (!strcmp(args[0], "node")) {
1412 int i;
1413 char c;
1414
William Lallemand1a748ae2015-05-19 16:37:23 +02001415 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1416 goto out;
1417
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001418 for (i=0; args[1][i]; i++) {
1419 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001420 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1421 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001422 break;
1423 }
1424
1425 if (!i || args[1][i]) {
1426 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1427 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1428 file, linenum, args[0]);
1429 err_code |= ERR_ALERT | ERR_FATAL;
1430 goto out;
1431 }
1432
1433 if (global.node)
1434 free(global.node);
1435
1436 global.node = strdup(args[1]);
1437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001439 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001441 if (global.pidfile != NULL) {
1442 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001443 err_code |= ERR_ALERT;
1444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445 }
1446 if (*(args[1]) == 0) {
1447 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001448 err_code |= ERR_ALERT | ERR_FATAL;
1449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450 }
1451 global.pidfile = strdup(args[1]);
1452 }
Emeric Bruned760922010-10-22 17:59:25 +02001453 else if (!strcmp(args[0], "unix-bind")) {
1454 int cur_arg = 1;
1455 while (*(args[cur_arg])) {
1456 if (!strcmp(args[cur_arg], "prefix")) {
1457 if (global.unix_bind.prefix != NULL) {
1458 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1459 err_code |= ERR_ALERT;
1460 cur_arg += 2;
1461 continue;
1462 }
1463
1464 if (*(args[cur_arg+1]) == 0) {
1465 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1466 err_code |= ERR_ALERT | ERR_FATAL;
1467 goto out;
1468 }
1469 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1470 cur_arg += 2;
1471 continue;
1472 }
1473
1474 if (!strcmp(args[cur_arg], "mode")) {
1475
1476 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1477 cur_arg += 2;
1478 continue;
1479 }
1480
1481 if (!strcmp(args[cur_arg], "uid")) {
1482
1483 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1484 cur_arg += 2;
1485 continue;
1486 }
1487
1488 if (!strcmp(args[cur_arg], "gid")) {
1489
1490 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1491 cur_arg += 2;
1492 continue;
1493 }
1494
1495 if (!strcmp(args[cur_arg], "user")) {
1496 struct passwd *user;
1497
1498 user = getpwnam(args[cur_arg + 1]);
1499 if (!user) {
1500 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1501 file, linenum, args[0], args[cur_arg + 1 ]);
1502 err_code |= ERR_ALERT | ERR_FATAL;
1503 goto out;
1504 }
1505
1506 global.unix_bind.ux.uid = user->pw_uid;
1507 cur_arg += 2;
1508 continue;
1509 }
1510
1511 if (!strcmp(args[cur_arg], "group")) {
1512 struct group *group;
1513
1514 group = getgrnam(args[cur_arg + 1]);
1515 if (!group) {
1516 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1517 file, linenum, args[0], args[cur_arg + 1 ]);
1518 err_code |= ERR_ALERT | ERR_FATAL;
1519 goto out;
1520 }
1521
1522 global.unix_bind.ux.gid = group->gr_gid;
1523 cur_arg += 2;
1524 continue;
1525 }
1526
Willy Tarreaub48f9582011-09-05 01:17:06 +02001527 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001528 file, linenum, args[0]);
1529 err_code |= ERR_ALERT | ERR_FATAL;
1530 goto out;
1531 }
1532 }
William Lallemand0f99e342011-10-12 17:50:54 +02001533 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1534 /* delete previous herited or defined syslog servers */
1535 struct logsrv *back;
1536 struct logsrv *tmp;
1537
1538 if (*(args[1]) != 0) {
1539 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1540 err_code |= ERR_ALERT | ERR_FATAL;
1541 goto out;
1542 }
1543
1544 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1545 LIST_DEL(&tmp->list);
1546 free(tmp);
1547 }
1548 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001549 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001550 struct sockaddr_storage *sk;
1551 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001552 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001553 int arg = 0;
1554 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001555
William Lallemand1a748ae2015-05-19 16:37:23 +02001556 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1557 goto out;
1558
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 if (*(args[1]) == 0 || *(args[2]) == 0) {
1560 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001561 err_code |= ERR_ALERT | ERR_FATAL;
1562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563 }
William Lallemand0f99e342011-10-12 17:50:54 +02001564
1565 logsrv = calloc(1, sizeof(struct logsrv));
1566
Willy Tarreau18324f52014-06-27 18:10:07 +02001567 /* just after the address, a length may be specified */
1568 if (strcmp(args[arg+2], "len") == 0) {
1569 len = atoi(args[arg+3]);
1570 if (len < 80 || len > 65535) {
1571 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1572 file, linenum, args[arg+3]);
1573 err_code |= ERR_ALERT | ERR_FATAL;
1574 goto out;
1575 }
1576 logsrv->maxlen = len;
1577
1578 /* skip these two args */
1579 arg += 2;
1580 }
1581 else
1582 logsrv->maxlen = MAX_SYSLOG_LEN;
1583
1584 if (logsrv->maxlen > global.max_syslog_len) {
1585 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02001586 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02001587 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001588 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02001589 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001590 }
1591
Dragan Dosen1322d092015-09-22 16:05:32 +02001592 /* after the length, a format may be specified */
1593 if (strcmp(args[arg+2], "format") == 0) {
1594 logsrv->format = get_log_format(args[arg+3]);
1595 if (logsrv->format < 0) {
1596 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1597 err_code |= ERR_ALERT | ERR_FATAL;
1598 goto out;
1599 }
1600
1601 /* skip these two args */
1602 arg += 2;
1603 }
1604
William Lallemand1a748ae2015-05-19 16:37:23 +02001605 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1606 goto out;
1607
Willy Tarreau18324f52014-06-27 18:10:07 +02001608 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001609 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001610 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001611 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001612 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001613 }
1614
William Lallemand0f99e342011-10-12 17:50:54 +02001615 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001616 if (*(args[arg+3])) {
1617 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001618 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001619 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001620 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001621 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622 }
1623 }
1624
William Lallemand0f99e342011-10-12 17:50:54 +02001625 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001626 if (*(args[arg+4])) {
1627 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001628 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001629 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001630 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001631 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001632 }
1633 }
1634
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001635 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001636 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001637 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001638 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001639 free(logsrv);
1640 goto out;
1641 }
1642 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001643
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001644 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001645 if (port1 != port2) {
1646 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1647 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001648 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001649 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001650 goto out;
1651 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001652
William Lallemand0f99e342011-10-12 17:50:54 +02001653 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001654 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001655 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001656 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001657
William Lallemand0f99e342011-10-12 17:50:54 +02001658 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001659 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001660 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1661 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001662
1663 if (global.log_send_hostname != NULL) {
1664 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1665 err_code |= ERR_ALERT;
1666 goto out;
1667 }
1668
1669 if (*(args[1]))
1670 name = args[1];
1671 else
1672 name = hostname;
1673
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001674 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001675 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001676 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001677 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1678 if (global.server_state_base != NULL) {
1679 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1680 err_code |= ERR_ALERT;
1681 goto out;
1682 }
1683
1684 if (!*(args[1])) {
1685 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1686 err_code |= ERR_FATAL;
1687 goto out;
1688 }
1689
1690 global.server_state_base = strdup(args[1]);
1691 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001692 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1693 if (global.server_state_file != NULL) {
1694 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1695 err_code |= ERR_ALERT;
1696 goto out;
1697 }
1698
1699 if (!*(args[1])) {
1700 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1701 err_code |= ERR_FATAL;
1702 goto out;
1703 }
1704
1705 global.server_state_file = strdup(args[1]);
1706 }
Kevinm48936af2010-12-22 16:08:21 +00001707 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001708 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1709 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001710 if (*(args[1]) == 0) {
1711 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1712 err_code |= ERR_ALERT | ERR_FATAL;
1713 goto out;
1714 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001715 chunk_destroy(&global.log_tag);
1716 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001717 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001718 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001719 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1720 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001721 if (global.spread_checks != 0) {
1722 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001723 err_code |= ERR_ALERT;
1724 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001725 }
1726 if (*(args[1]) == 0) {
1727 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001728 err_code |= ERR_ALERT | ERR_FATAL;
1729 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001730 }
1731 global.spread_checks = atol(args[1]);
1732 if (global.spread_checks < 0 || global.spread_checks > 50) {
1733 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001734 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001735 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001737 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1738 const char *err;
1739 unsigned int val;
1740
William Lallemand1a748ae2015-05-19 16:37:23 +02001741 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1742 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001743 if (*(args[1]) == 0) {
1744 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1745 err_code |= ERR_ALERT | ERR_FATAL;
1746 goto out;
1747 }
1748
1749 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1750 if (err) {
1751 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1752 err_code |= ERR_ALERT | ERR_FATAL;
1753 }
1754 global.max_spread_checks = val;
1755 if (global.max_spread_checks < 0) {
1756 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1757 err_code |= ERR_ALERT | ERR_FATAL;
1758 }
1759 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001760 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1761#ifdef USE_CPU_AFFINITY
1762 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001763 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001764 unsigned long cpus = 0;
1765
1766 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001767 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001768 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001769 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001770 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001771 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001772 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001773 proc = atol(args[1]);
1774 if (proc >= 1 && proc <= LONGBITS)
1775 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001776 }
1777
1778 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001779 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",
1780 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
1783 }
1784
1785 cur_arg = 2;
1786 while (*args[cur_arg]) {
1787 unsigned int low, high;
1788
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001789 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001790 char *dash = strchr(args[cur_arg], '-');
1791
1792 low = high = str2uic(args[cur_arg]);
1793 if (dash)
1794 high = str2uic(dash + 1);
1795
1796 if (high < low) {
1797 unsigned int swap = low;
1798 low = high;
1799 high = swap;
1800 }
1801
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001802 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001803 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001804 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001805 err_code |= ERR_ALERT | ERR_FATAL;
1806 goto out;
1807 }
1808
1809 while (low <= high)
1810 cpus |= 1UL << low++;
1811 }
1812 else {
1813 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1814 file, linenum, args[0], args[cur_arg]);
1815 err_code |= ERR_ALERT | ERR_FATAL;
1816 goto out;
1817 }
1818 cur_arg++;
1819 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001820 for (i = 0; i < LONGBITS; i++)
1821 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001822 global.cpu_map[i] = cpus;
1823#else
1824 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1825 err_code |= ERR_ALERT | ERR_FATAL;
1826 goto out;
1827#endif
1828 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001829 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1830 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1831 goto out;
1832
1833 if (*(args[2]) == 0) {
1834 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1835 err_code |= ERR_ALERT | ERR_FATAL;
1836 goto out;
1837 }
1838
1839 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1840 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1841 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1842 err_code |= ERR_ALERT | ERR_FATAL;
1843 goto out;
1844 }
1845 }
1846 else if (!strcmp(args[0], "unsetenv")) {
1847 int arg;
1848
1849 if (*(args[1]) == 0) {
1850 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1851 err_code |= ERR_ALERT | ERR_FATAL;
1852 goto out;
1853 }
1854
1855 for (arg = 1; *args[arg]; arg++) {
1856 if (unsetenv(args[arg]) != 0) {
1857 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1858 err_code |= ERR_ALERT | ERR_FATAL;
1859 goto out;
1860 }
1861 }
1862 }
1863 else if (!strcmp(args[0], "resetenv")) {
1864 extern char **environ;
1865 char **env = environ;
1866
1867 /* args contain variable names to keep, one per argument */
1868 while (*env) {
1869 int arg;
1870
1871 /* look for current variable in among all those we want to keep */
1872 for (arg = 1; *args[arg]; arg++) {
1873 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1874 (*env)[strlen(args[arg])] == '=')
1875 break;
1876 }
1877
1878 /* delete this variable */
1879 if (!*args[arg]) {
1880 char *delim = strchr(*env, '=');
1881
1882 if (!delim || delim - *env >= trash.size) {
1883 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1884 err_code |= ERR_ALERT | ERR_FATAL;
1885 goto out;
1886 }
1887
1888 memcpy(trash.str, *env, delim - *env);
1889 trash.str[delim - *env] = 0;
1890
1891 if (unsetenv(trash.str) != 0) {
1892 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1893 err_code |= ERR_ALERT | ERR_FATAL;
1894 goto out;
1895 }
1896 }
1897 else
1898 env++;
1899 }
1900 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001902 struct cfg_kw_list *kwl;
1903 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001904 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001905
1906 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1907 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1908 if (kwl->kw[index].section != CFG_GLOBAL)
1909 continue;
1910 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001911 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001912 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001913 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001914 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001915 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001916 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001917 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001918 err_code |= ERR_WARN;
1919 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001920 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001921 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001922 }
1923 }
1924 }
1925
Willy Tarreaubaaee002006-06-26 02:48:02 +02001926 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001927 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001928 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001929
Willy Tarreau058e9072009-07-20 09:30:05 +02001930 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001931 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001932 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933}
1934
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001935void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001937 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938 defproxy.mode = PR_MODE_TCP;
1939 defproxy.state = PR_STNEW;
1940 defproxy.maxconn = cfg_maxpconn;
1941 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001942 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001943
Simon Horman66183002013-02-23 10:16:43 +09001944 defproxy.defsrv.check.inter = DEF_CHKINTR;
1945 defproxy.defsrv.check.fastinter = 0;
1946 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001947 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1948 defproxy.defsrv.agent.fastinter = 0;
1949 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001950 defproxy.defsrv.check.rise = DEF_RISETIME;
1951 defproxy.defsrv.check.fall = DEF_FALLTIME;
1952 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1953 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001954 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001955 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001956 defproxy.defsrv.maxqueue = 0;
1957 defproxy.defsrv.minconn = 0;
1958 defproxy.defsrv.maxconn = 0;
1959 defproxy.defsrv.slowstart = 0;
1960 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1961 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1962 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001963
1964 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001965 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966}
1967
Willy Tarreauade5ec42010-01-28 19:33:49 +01001968
Willy Tarreau63af98d2014-05-18 08:11:41 +02001969/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1970 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1971 * ERR_FATAL in case of error.
1972 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001973static int create_cond_regex_rule(const char *file, int line,
1974 struct proxy *px, int dir, int action, int flags,
1975 const char *cmd, const char *reg, const char *repl,
1976 const char **cond_start)
1977{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001978 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001979 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001980 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001981 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001982 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001983 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001984 int cs;
1985 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001986
1987 if (px == &defproxy) {
1988 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001989 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001990 goto err;
1991 }
1992
1993 if (*reg == 0) {
1994 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001995 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001996 goto err;
1997 }
1998
1999 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002000 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002001
Willy Tarreau5321c422010-01-28 20:35:13 +01002002 if (cond_start &&
2003 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002004 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
2005 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
2006 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002007 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002008 goto err;
2009 }
2010 }
2011 else if (cond_start && **cond_start) {
2012 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
2013 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002014 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002015 goto err;
2016 }
2017
Willy Tarreau63af98d2014-05-18 08:11:41 +02002018 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002019 (dir == SMP_OPT_DIR_REQ) ?
2020 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
2021 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
2022 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01002023
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002024 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01002025 if (!preg) {
2026 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002027 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002028 goto err;
2029 }
2030
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002031 cs = !(flags & REG_ICASE);
2032 cap = !(flags & REG_NOSUB);
2033 error = NULL;
2034 if (!regex_comp(reg, preg, cs, cap, &error)) {
2035 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
2036 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002037 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002038 goto err;
2039 }
2040
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002041 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01002042 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002043 if (repl && err) {
2044 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
2045 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002046 ret_code |= ERR_ALERT | ERR_FATAL;
2047 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002048 }
2049
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002050 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002051 ret_code |= ERR_WARN;
2052
2053 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002054
Willy Tarreau63af98d2014-05-18 08:11:41 +02002055 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002056 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002057 err:
2058 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002059 free(errmsg);
2060 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002061}
2062
Willy Tarreaubaaee002006-06-26 02:48:02 +02002063/*
William Lallemand51097192015-04-14 16:35:22 +02002064 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02002065 * Returns the error code, 0 if OK, or any combination of :
2066 * - ERR_ABORT: must abort ASAP
2067 * - ERR_FATAL: we can continue parsing but not start the service
2068 * - ERR_WARN: a warning has been emitted
2069 * - ERR_ALERT: an alert has been emitted
2070 * Only the two first ones can stop processing, the two others are just
2071 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002072 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002073int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2074{
2075 static struct peers *curpeers = NULL;
2076 struct peer *newpeer = NULL;
2077 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002078 struct bind_conf *bind_conf;
2079 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002080 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002081 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002082
2083 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002084 if (!*args[1]) {
2085 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002086 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002087 goto out;
2088 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002089
William Lallemand6e62fb62015-04-28 16:55:23 +02002090 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2091 goto out;
2092
Emeric Brun32da3c42010-09-23 18:39:19 +02002093 err = invalid_char(args[1]);
2094 if (err) {
2095 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2096 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002097 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002098 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002099 }
2100
2101 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2102 /*
2103 * If there are two proxies with the same name only following
2104 * combinations are allowed:
2105 */
2106 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002107 Alert("Parsing [%s:%d]: peers section '%s' has the same name as another peers section declared at %s:%d.\n",
Emeric Brun32da3c42010-09-23 18:39:19 +02002108 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002109 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002110 }
2111 }
2112
2113 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
2114 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2115 err_code |= ERR_ALERT | ERR_ABORT;
2116 goto out;
2117 }
2118
2119 curpeers->next = peers;
2120 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002121 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002122 curpeers->conf.line = linenum;
2123 curpeers->last_change = now.tv_sec;
2124 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002125 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002126 }
2127 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002128 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002129 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002130 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002131
2132 if (!*args[2]) {
2133 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2134 file, linenum, args[0]);
2135 err_code |= ERR_ALERT | ERR_FATAL;
2136 goto out;
2137 }
2138
2139 err = invalid_char(args[1]);
2140 if (err) {
2141 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2142 file, linenum, *err, args[1]);
2143 err_code |= ERR_ALERT | ERR_FATAL;
2144 goto out;
2145 }
2146
2147 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2148 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2149 err_code |= ERR_ALERT | ERR_ABORT;
2150 goto out;
2151 }
2152
2153 /* the peers are linked backwards first */
2154 curpeers->count++;
2155 newpeer->next = curpeers->remote;
2156 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002157 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002158 newpeer->conf.line = linenum;
2159
2160 newpeer->last_change = now.tv_sec;
2161 newpeer->id = strdup(args[1]);
2162
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002163 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002164 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002165 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002168 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002169
2170 proto = protocol_by_family(sk->ss_family);
2171 if (!proto || !proto->connect) {
2172 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2173 file, linenum, args[0], args[1]);
2174 err_code |= ERR_ALERT | ERR_FATAL;
2175 goto out;
2176 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002177
2178 if (port1 != port2) {
2179 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2180 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002181 err_code |= ERR_ALERT | ERR_FATAL;
2182 goto out;
2183 }
2184
Willy Tarreau2aa38802013-02-20 19:20:59 +01002185 if (!port1) {
2186 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2187 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002188 err_code |= ERR_ALERT | ERR_FATAL;
2189 goto out;
2190 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002191
Emeric Brun32da3c42010-09-23 18:39:19 +02002192 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002193 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002194 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002195 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002196
Emeric Brun32da3c42010-09-23 18:39:19 +02002197 if (strcmp(newpeer->id, localpeer) == 0) {
2198 /* Current is local peer, it define a frontend */
2199 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002200 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002201
2202 if (!curpeers->peers_fe) {
2203 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2204 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2205 err_code |= ERR_ALERT | ERR_ABORT;
2206 goto out;
2207 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002208
Willy Tarreau237250c2011-07-29 01:49:03 +02002209 init_new_proxy(curpeers->peers_fe);
2210 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002211 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002212 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2213 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002214 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002215
2216 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2217
Willy Tarreau902636f2013-03-10 19:44:48 +01002218 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2219 if (errmsg && *errmsg) {
2220 indent_msg(&errmsg, 2);
2221 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002222 }
2223 else
2224 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2225 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002226 err_code |= ERR_FATAL;
2227 goto out;
2228 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002229
2230 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002231 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002232 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2233 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002234 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002235 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002236 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002237 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002238 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2239 global.maxsock += l->maxconn;
2240 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002241 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002242 else {
2243 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2244 file, linenum, args[0], args[1],
2245 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2246 err_code |= ERR_FATAL;
2247 goto out;
2248 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002249 }
2250 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002251 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2252 curpeers->state = PR_STSTOPPED;
2253 }
2254 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2255 curpeers->state = PR_STNEW;
2256 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002257 else if (*args[0] != 0) {
2258 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
2261 }
2262
2263out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002264 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002265 return err_code;
2266}
2267
Baptiste Assmann325137d2015-04-13 23:40:55 +02002268/*
2269 * Parse a <resolvers> section.
2270 * Returns the error code, 0 if OK, or any combination of :
2271 * - ERR_ABORT: must abort ASAP
2272 * - ERR_FATAL: we can continue parsing but not start the service
2273 * - ERR_WARN: a warning has been emitted
2274 * - ERR_ALERT: an alert has been emitted
2275 * Only the two first ones can stop processing, the two others are just
2276 * indicators.
2277 */
2278int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2279{
2280 static struct dns_resolvers *curr_resolvers = NULL;
2281 struct dns_nameserver *newnameserver = NULL;
2282 const char *err;
2283 int err_code = 0;
2284 char *errmsg = NULL;
2285
2286 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2287 if (!*args[1]) {
2288 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2289 err_code |= ERR_ALERT | ERR_ABORT;
2290 goto out;
2291 }
2292
2293 err = invalid_char(args[1]);
2294 if (err) {
2295 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2296 file, linenum, *err, args[0], args[1]);
2297 err_code |= ERR_ALERT | ERR_ABORT;
2298 goto out;
2299 }
2300
2301 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2302 /* Error if two resolvers owns the same name */
2303 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2304 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2305 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2306 err_code |= ERR_ALERT | ERR_ABORT;
2307 }
2308 }
2309
2310 if ((curr_resolvers = (struct dns_resolvers *)calloc(1, sizeof(struct dns_resolvers))) == NULL) {
2311 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2312 err_code |= ERR_ALERT | ERR_ABORT;
2313 goto out;
2314 }
2315
2316 /* default values */
2317 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2318 curr_resolvers->conf.file = strdup(file);
2319 curr_resolvers->conf.line = linenum;
2320 curr_resolvers->id = strdup(args[1]);
2321 curr_resolvers->query_ids = EB_ROOT;
2322 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002323 curr_resolvers->hold.valid = 10000;
2324 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002325 curr_resolvers->resolve_retries = 3;
2326 LIST_INIT(&curr_resolvers->nameserver_list);
2327 LIST_INIT(&curr_resolvers->curr_resolution);
2328 }
2329 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2330 struct sockaddr_storage *sk;
2331 int port1, port2;
2332 struct protocol *proto;
2333
2334 if (!*args[2]) {
2335 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2336 file, linenum, args[0]);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340
2341 err = invalid_char(args[1]);
2342 if (err) {
2343 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2344 file, linenum, *err, args[1]);
2345 err_code |= ERR_ALERT | ERR_FATAL;
2346 goto out;
2347 }
2348
Baptiste Assmanna315c552015-11-02 22:55:49 +01002349 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2350 /* Error if two resolvers owns the same name */
2351 if (strcmp(newnameserver->id, args[1]) == 0) {
2352 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2353 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2354 err_code |= ERR_ALERT | ERR_FATAL;
2355 }
2356 }
2357
Baptiste Assmann325137d2015-04-13 23:40:55 +02002358 if ((newnameserver = (struct dns_nameserver *)calloc(1, sizeof(struct dns_nameserver))) == NULL) {
2359 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2360 err_code |= ERR_ALERT | ERR_ABORT;
2361 goto out;
2362 }
2363
2364 /* the nameservers are linked backward first */
2365 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2366 curr_resolvers->count_nameservers++;
2367 newnameserver->resolvers = curr_resolvers;
2368 newnameserver->conf.file = strdup(file);
2369 newnameserver->conf.line = linenum;
2370 newnameserver->id = strdup(args[1]);
2371
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002372 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002373 if (!sk) {
2374 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
2377 }
2378
2379 proto = protocol_by_family(sk->ss_family);
2380 if (!proto || !proto->connect) {
2381 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2382 file, linenum, args[0], args[1]);
2383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
2385 }
2386
2387 if (port1 != port2) {
2388 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2389 file, linenum, args[0], args[1], args[2]);
2390 err_code |= ERR_ALERT | ERR_FATAL;
2391 goto out;
2392 }
2393
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002394 if (!port1 && !port2) {
2395 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2396 file, linenum, args[0], args[1]);
2397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
2399 }
2400
Baptiste Assmann325137d2015-04-13 23:40:55 +02002401 newnameserver->addr = *sk;
2402 }
2403 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2404 const char *res;
2405 unsigned int time;
2406
2407 if (!*args[2]) {
2408 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2409 file, linenum, args[0]);
2410 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
2413 }
2414 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2415 if (res) {
2416 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2417 file, linenum, *res, args[0]);
2418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
2420 }
2421 if (strcmp(args[1], "valid") == 0)
2422 curr_resolvers->hold.valid = time;
2423 else {
2424 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2425 file, linenum, args[0], args[1]);
2426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
2428 }
2429
2430 }
2431 else if (strcmp(args[0], "resolve_retries") == 0) {
2432 if (!*args[1]) {
2433 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2434 file, linenum, args[0]);
2435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
2437 }
2438 curr_resolvers->resolve_retries = atoi(args[1]);
2439 }
2440 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002441 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002442 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2443 file, linenum, args[0]);
2444 err_code |= ERR_ALERT | ERR_FATAL;
2445 goto out;
2446 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002447 else if (strcmp(args[1], "retry") == 0) {
2448 const char *res;
2449 unsigned int timeout_retry;
2450
2451 if (!*args[2]) {
2452 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2453 file, linenum, args[0], args[1]);
2454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
2456 }
2457 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2458 if (res) {
2459 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2460 file, linenum, *res, args[0], args[1]);
2461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
2463 }
2464 curr_resolvers->timeout.retry = timeout_retry;
2465 }
2466 else {
2467 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2468 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
2471 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002472 } /* neither "nameserver" nor "resolvers" */
2473 else if (*args[0] != 0) {
2474 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
2477 }
2478
2479 out:
2480 free(errmsg);
2481 return err_code;
2482}
Simon Horman0d16a402015-01-30 11:22:58 +09002483
2484/*
William Lallemand51097192015-04-14 16:35:22 +02002485 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002486 * Returns the error code, 0 if OK, or any combination of :
2487 * - ERR_ABORT: must abort ASAP
2488 * - ERR_FATAL: we can continue parsing but not start the service
2489 * - ERR_WARN: a warning has been emitted
2490 * - ERR_ALERT: an alert has been emitted
2491 * Only the two first ones can stop processing, the two others are just
2492 * indicators.
2493 */
2494int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2495{
2496 static struct mailers *curmailers = NULL;
2497 struct mailer *newmailer = NULL;
2498 const char *err;
2499 int err_code = 0;
2500 char *errmsg = NULL;
2501
2502 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2503 if (!*args[1]) {
2504 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2505 err_code |= ERR_ALERT | ERR_ABORT;
2506 goto out;
2507 }
2508
2509 err = invalid_char(args[1]);
2510 if (err) {
2511 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2512 file, linenum, *err, args[0], args[1]);
2513 err_code |= ERR_ALERT | ERR_ABORT;
2514 goto out;
2515 }
2516
2517 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2518 /*
2519 * If there are two proxies with the same name only following
2520 * combinations are allowed:
2521 */
2522 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002523 Alert("Parsing [%s:%d]: mailers section '%s' has the same name as another mailers section declared at %s:%d.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002524 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002525 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002526 }
2527 }
2528
2529 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2530 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2531 err_code |= ERR_ALERT | ERR_ABORT;
2532 goto out;
2533 }
2534
2535 curmailers->next = mailers;
2536 mailers = curmailers;
2537 curmailers->conf.file = strdup(file);
2538 curmailers->conf.line = linenum;
2539 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002540 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2541 * But need enough time so that timeouts don't occur
2542 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002543 }
2544 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2545 struct sockaddr_storage *sk;
2546 int port1, port2;
2547 struct protocol *proto;
2548
2549 if (!*args[2]) {
2550 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2551 file, linenum, args[0]);
2552 err_code |= ERR_ALERT | ERR_FATAL;
2553 goto out;
2554 }
2555
2556 err = invalid_char(args[1]);
2557 if (err) {
2558 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2559 file, linenum, *err, args[1]);
2560 err_code |= ERR_ALERT | ERR_FATAL;
2561 goto out;
2562 }
2563
2564 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2565 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2566 err_code |= ERR_ALERT | ERR_ABORT;
2567 goto out;
2568 }
2569
2570 /* the mailers are linked backwards first */
2571 curmailers->count++;
2572 newmailer->next = curmailers->mailer_list;
2573 curmailers->mailer_list = newmailer;
2574 newmailer->mailers = curmailers;
2575 newmailer->conf.file = strdup(file);
2576 newmailer->conf.line = linenum;
2577
2578 newmailer->id = strdup(args[1]);
2579
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002580 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002581 if (!sk) {
2582 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2583 err_code |= ERR_ALERT | ERR_FATAL;
2584 goto out;
2585 }
2586
2587 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002588 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2589 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002590 file, linenum, args[0], args[1]);
2591 err_code |= ERR_ALERT | ERR_FATAL;
2592 goto out;
2593 }
2594
2595 if (port1 != port2) {
2596 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2597 file, linenum, args[0], args[1], args[2]);
2598 err_code |= ERR_ALERT | ERR_FATAL;
2599 goto out;
2600 }
2601
2602 if (!port1) {
2603 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2604 file, linenum, args[0], args[1], args[2]);
2605 err_code |= ERR_ALERT | ERR_FATAL;
2606 goto out;
2607 }
2608
2609 newmailer->addr = *sk;
2610 newmailer->proto = proto;
2611 newmailer->xprt = &raw_sock;
2612 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002613 }
2614 else if (strcmp(args[0], "timeout") == 0) {
2615 if (!*args[1]) {
2616 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2617 file, linenum, args[0]);
2618 err_code |= ERR_ALERT | ERR_FATAL;
2619 goto out;
2620 }
2621 else if (strcmp(args[1], "mail") == 0) {
2622 const char *res;
2623 unsigned int timeout_mail;
2624 if (!*args[2]) {
2625 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2626 file, linenum, args[0], args[1]);
2627 err_code |= ERR_ALERT | ERR_FATAL;
2628 goto out;
2629 }
2630 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2631 if (res) {
2632 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2633 file, linenum, *res, args[0]);
2634 err_code |= ERR_ALERT | ERR_FATAL;
2635 goto out;
2636 }
2637 if (timeout_mail <= 0) {
2638 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2639 err_code |= ERR_ALERT | ERR_FATAL;
2640 goto out;
2641 }
2642 curmailers->timeout.mail = timeout_mail;
2643 } else {
2644 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2645 file, linenum, args[0], args[1]);
2646 err_code |= ERR_ALERT | ERR_FATAL;
2647 goto out;
2648 }
2649 }
Simon Horman0d16a402015-01-30 11:22:58 +09002650 else if (*args[0] != 0) {
2651 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2652 err_code |= ERR_ALERT | ERR_FATAL;
2653 goto out;
2654 }
2655
2656out:
2657 free(errmsg);
2658 return err_code;
2659}
2660
Simon Horman9dc49962015-01-30 11:22:59 +09002661static void free_email_alert(struct proxy *p)
2662{
2663 free(p->email_alert.mailers.name);
2664 p->email_alert.mailers.name = NULL;
2665 free(p->email_alert.from);
2666 p->email_alert.from = NULL;
2667 free(p->email_alert.to);
2668 p->email_alert.to = NULL;
2669 free(p->email_alert.myhostname);
2670 p->email_alert.myhostname = NULL;
2671}
2672
Willy Tarreau3842f002009-06-14 11:39:52 +02002673int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002674{
2675 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002676 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002677 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002678 int rc;
2679 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002680 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002681 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002682 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002683 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002684 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002685
Willy Tarreau977b8e42006-12-29 14:19:17 +01002686 if (!strcmp(args[0], "listen"))
2687 rc = PR_CAP_LISTEN;
2688 else if (!strcmp(args[0], "frontend"))
2689 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002690 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002691 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002692 else
2693 rc = PR_CAP_NONE;
2694
2695 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002696 if (!*args[1]) {
2697 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2698 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2699 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002700 err_code |= ERR_ALERT | ERR_ABORT;
2701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002702 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002703
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002704 err = invalid_char(args[1]);
2705 if (err) {
2706 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2707 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002708 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002709 }
2710
Willy Tarreau8f50b682015-05-26 11:45:02 +02002711 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2712 if (curproxy) {
2713 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2714 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2715 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002716 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002717 }
2718
Willy Tarreaubaaee002006-06-26 02:48:02 +02002719 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2720 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002721 err_code |= ERR_ALERT | ERR_ABORT;
2722 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002723 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002724
Willy Tarreau97cb7802010-01-03 20:23:58 +01002725 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002726 curproxy->next = proxy;
2727 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002728 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2729 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002730 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002732 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002733 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002734
William Lallemand6e62fb62015-04-28 16:55:23 +02002735 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2736 if (curproxy->cap & PR_CAP_FE)
2737 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2738 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002739 }
2740
2741 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002742 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002743 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002744
Willy Tarreaubaaee002006-06-26 02:48:02 +02002745 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002746 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002747 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002748 curproxy->no_options = defproxy.no_options;
2749 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002750 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002751 curproxy->except_net = defproxy.except_net;
2752 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002753 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002754 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002755
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002756 if (defproxy.fwdfor_hdr_len) {
2757 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2758 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2759 }
2760
Willy Tarreaub86db342009-11-30 11:50:16 +01002761 if (defproxy.orgto_hdr_len) {
2762 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2763 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2764 }
2765
Mark Lamourinec2247f02012-01-04 13:02:01 -05002766 if (defproxy.server_id_hdr_len) {
2767 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2768 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2769 }
2770
Willy Tarreau977b8e42006-12-29 14:19:17 +01002771 if (curproxy->cap & PR_CAP_FE) {
2772 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002773 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002774 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002775
2776 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002777 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2778 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002779
2780 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2781 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782
Willy Tarreau977b8e42006-12-29 14:19:17 +01002783 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002784 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002785 curproxy->fullconn = defproxy.fullconn;
2786 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002787 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002788 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002789
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002790 if (defproxy.check_req) {
2791 curproxy->check_req = calloc(1, defproxy.check_len);
2792 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2793 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002794 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002795
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002796 if (defproxy.expect_str) {
2797 curproxy->expect_str = strdup(defproxy.expect_str);
2798 if (defproxy.expect_regex) {
2799 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002800 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2801 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002802 }
2803 }
2804
Willy Tarreau67402132012-05-31 20:40:20 +02002805 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002806 if (defproxy.cookie_name)
2807 curproxy->cookie_name = strdup(defproxy.cookie_name);
2808 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002809 if (defproxy.cookie_domain)
2810 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002811
Willy Tarreau31936852010-10-06 16:59:56 +02002812 if (defproxy.cookie_maxidle)
2813 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2814
2815 if (defproxy.cookie_maxlife)
2816 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2817
Emeric Brun647caf12009-06-30 17:57:00 +02002818 if (defproxy.rdp_cookie_name)
2819 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2820 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2821
Willy Tarreau01732802007-11-01 22:48:15 +01002822 if (defproxy.url_param_name)
2823 curproxy->url_param_name = strdup(defproxy.url_param_name);
2824 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002825
Benoitaffb4812009-03-25 13:02:10 +01002826 if (defproxy.hh_name)
2827 curproxy->hh_name = strdup(defproxy.hh_name);
2828 curproxy->hh_len = defproxy.hh_len;
2829 curproxy->hh_match_domain = defproxy.hh_match_domain;
2830
Willy Tarreauef9a3602012-12-08 22:29:20 +01002831 if (defproxy.conn_src.iface_name)
2832 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2833 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002834 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002835#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002836 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002837#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002838 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002839 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002841 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002842 if (defproxy.capture_name)
2843 curproxy->capture_name = strdup(defproxy.capture_name);
2844 curproxy->capture_namelen = defproxy.capture_namelen;
2845 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002846 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002847
Willy Tarreau977b8e42006-12-29 14:19:17 +01002848 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002849 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002850 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002851 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002852 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002853 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002854 curproxy->mon_net = defproxy.mon_net;
2855 curproxy->mon_mask = defproxy.mon_mask;
2856 if (defproxy.monitor_uri)
2857 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2858 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002859 if (defproxy.defbe.name)
2860 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002861
2862 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002863 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2864 if (curproxy->conf.logformat_string &&
2865 curproxy->conf.logformat_string != default_http_log_format &&
2866 curproxy->conf.logformat_string != default_tcp_log_format &&
2867 curproxy->conf.logformat_string != clf_http_log_format)
2868 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2869
2870 if (defproxy.conf.lfs_file) {
2871 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2872 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2873 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002874
2875 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2876 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2877 if (curproxy->conf.logformat_sd_string &&
2878 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2879 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2880
2881 if (defproxy.conf.lfsd_file) {
2882 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2883 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2884 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002885 }
2886
2887 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002888 curproxy->timeout.connect = defproxy.timeout.connect;
2889 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002890 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002891 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002892 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002893 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002894 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002895 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002896 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002897 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002898 }
2899
Willy Tarreaubaaee002006-06-26 02:48:02 +02002900 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002901 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002902
2903 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002904 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002905 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002906 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002907 LIST_INIT(&node->list);
2908 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2909 }
2910
Willy Tarreau62a61232013-04-12 18:13:46 +02002911 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2912 if (curproxy->conf.uniqueid_format_string)
2913 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2914
Dragan Dosen43885c72015-10-01 13:18:13 +02002915 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002916
Willy Tarreau62a61232013-04-12 18:13:46 +02002917 if (defproxy.conf.uif_file) {
2918 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2919 curproxy->conf.uif_line = defproxy.conf.uif_line;
2920 }
William Lallemanda73203e2012-03-12 12:48:57 +01002921
2922 /* copy default header unique id */
2923 if (defproxy.header_unique_id)
2924 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2925
William Lallemand82fe75c2012-10-23 10:25:10 +02002926 /* default compression options */
2927 if (defproxy.comp != NULL) {
2928 curproxy->comp = calloc(1, sizeof(struct comp));
2929 curproxy->comp->algos = defproxy.comp->algos;
2930 curproxy->comp->types = defproxy.comp->types;
2931 }
2932
Willy Tarreaubaaee002006-06-26 02:48:02 +02002933 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002934 curproxy->conf.used_listener_id = EB_ROOT;
2935 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002936
Simon Horman98637e52014-06-20 12:30:16 +09002937 if (defproxy.check_path)
2938 curproxy->check_path = strdup(defproxy.check_path);
2939 if (defproxy.check_command)
2940 curproxy->check_command = strdup(defproxy.check_command);
2941
Simon Horman9dc49962015-01-30 11:22:59 +09002942 if (defproxy.email_alert.mailers.name)
2943 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2944 if (defproxy.email_alert.from)
2945 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2946 if (defproxy.email_alert.to)
2947 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2948 if (defproxy.email_alert.myhostname)
2949 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002950 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002951 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002952
Willy Tarreau93893792009-07-23 13:19:11 +02002953 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002954 }
2955 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2956 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002957 /* FIXME-20070101: we should do this too at the end of the
2958 * config parsing to free all default values.
2959 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002960 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2961 err_code |= ERR_ABORT;
2962 goto out;
2963 }
2964
Willy Tarreaua534fea2008-08-03 12:19:50 +02002965 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002966 free(defproxy.check_command);
2967 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002968 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002969 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002970 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002971 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002972 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002973 free(defproxy.capture_name);
2974 free(defproxy.monitor_uri);
2975 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002976 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002977 free(defproxy.fwdfor_hdr_name);
2978 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002979 free(defproxy.orgto_hdr_name);
2980 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002981 free(defproxy.server_id_hdr_name);
2982 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002983 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002984 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002985 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002986 free(defproxy.expect_regex);
2987 defproxy.expect_regex = NULL;
2988 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002989
Willy Tarreau62a61232013-04-12 18:13:46 +02002990 if (defproxy.conf.logformat_string != default_http_log_format &&
2991 defproxy.conf.logformat_string != default_tcp_log_format &&
2992 defproxy.conf.logformat_string != clf_http_log_format)
2993 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002994
Willy Tarreau62a61232013-04-12 18:13:46 +02002995 free(defproxy.conf.uniqueid_format_string);
2996 free(defproxy.conf.lfs_file);
2997 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002998 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002999 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02003000
Dragan Dosen0b85ece2015-09-25 19:17:44 +02003001 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
3002 free(defproxy.conf.logformat_sd_string);
3003 free(defproxy.conf.lfsd_file);
3004
Willy Tarreaua534fea2008-08-03 12:19:50 +02003005 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003006 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01003007
Willy Tarreaubaaee002006-06-26 02:48:02 +02003008 /* we cannot free uri_auth because it might already be used */
3009 init_default_instance();
3010 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003011 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
3012 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003013 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02003014 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003015 }
3016 else if (curproxy == NULL) {
3017 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003020 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003021
3022 /* update the current file and line being parsed */
3023 curproxy->conf.args.file = curproxy->conf.file;
3024 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003025
3026 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02003027 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
3028 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
3029 if (err_code & ERR_FATAL)
3030 goto out;
3031 }
3032 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003033 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003034 int cur_arg;
3035
Willy Tarreaubaaee002006-06-26 02:48:02 +02003036 if (curproxy == &defproxy) {
3037 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003038 err_code |= ERR_ALERT | ERR_FATAL;
3039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003041 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003042 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003043
Willy Tarreau24709282013-03-10 21:32:12 +01003044 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003045 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003047 err_code |= ERR_ALERT | ERR_FATAL;
3048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003049 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003050
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003051 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003052
3053 /* use default settings for unix sockets */
3054 bind_conf->ux.uid = global.unix_bind.ux.uid;
3055 bind_conf->ux.gid = global.unix_bind.ux.gid;
3056 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003057
3058 /* NOTE: the following line might create several listeners if there
3059 * are comma-separated IPs or port ranges. So all further processing
3060 * will have to be applied to all listeners created after last_listen.
3061 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003062 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3063 if (errmsg && *errmsg) {
3064 indent_msg(&errmsg, 2);
3065 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003066 }
3067 else
3068 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3069 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003070 err_code |= ERR_ALERT | ERR_FATAL;
3071 goto out;
3072 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003073
Willy Tarreau4348fad2012-09-20 16:48:07 +02003074 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3075 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003076 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003077 }
3078
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003079 cur_arg = 2;
3080 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003081 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003082 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003083 char *err;
3084
Willy Tarreau26982662012-09-12 23:17:10 +02003085 kw = bind_find_kw(args[cur_arg]);
3086 if (kw) {
3087 char *err = NULL;
3088 int code;
3089
3090 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003091 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3092 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003093 cur_arg += 1 + kw->skip ;
3094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
3096 }
3097
Willy Tarreau4348fad2012-09-20 16:48:07 +02003098 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003099 err_code |= code;
3100
3101 if (code) {
3102 if (err && *err) {
3103 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003104 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003105 }
3106 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003107 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3108 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003109 if (code & ERR_FATAL) {
3110 free(err);
3111 cur_arg += 1 + kw->skip;
3112 goto out;
3113 }
3114 }
3115 free(err);
3116 cur_arg += 1 + kw->skip;
3117 continue;
3118 }
3119
Willy Tarreau8638f482012-09-18 18:01:17 +02003120 err = NULL;
3121 if (!bind_dumped) {
3122 bind_dump_kws(&err);
3123 indent_msg(&err, 4);
3124 bind_dumped = 1;
3125 }
3126
3127 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3128 file, linenum, args[0], args[1], args[cur_arg],
3129 err ? " Registered keywords :" : "", err ? err : "");
3130 free(err);
3131
Willy Tarreau93893792009-07-23 13:19:11 +02003132 err_code |= ERR_ALERT | ERR_FATAL;
3133 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003134 }
Willy Tarreau93893792009-07-23 13:19:11 +02003135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136 }
3137 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003138 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003139 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3140 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003141 err_code |= ERR_ALERT | ERR_FATAL;
3142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003143 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003144 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003145 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003146
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 /* flush useless bits */
3148 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003151 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003152 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003153 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003154
William Lallemanddf1425a2015-04-28 20:17:49 +02003155 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3156 goto out;
3157
Willy Tarreau1c47f852006-07-09 08:22:27 +02003158 if (!*args[1]) {
3159 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3160 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003161 err_code |= ERR_ALERT | ERR_FATAL;
3162 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003163 }
3164
Willy Tarreaua534fea2008-08-03 12:19:50 +02003165 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003166 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003167 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003168 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003169 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3170
Willy Tarreau93893792009-07-23 13:19:11 +02003171 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003172 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003174 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3175 goto out;
3176
Willy Tarreaubaaee002006-06-26 02:48:02 +02003177 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3178 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3179 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3180 else {
3181 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003182 err_code |= ERR_ALERT | ERR_FATAL;
3183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 }
3185 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003186 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003187 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003188
3189 if (curproxy == &defproxy) {
3190 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3191 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003194 }
3195
William Lallemanddf1425a2015-04-28 20:17:49 +02003196 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3197 goto out;
3198
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003199 if (!*args[1]) {
3200 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3201 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003202 err_code |= ERR_ALERT | ERR_FATAL;
3203 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003204 }
3205
3206 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003207 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003208 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003209
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003210 if (curproxy->uuid <= 0) {
3211 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003212 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003213 err_code |= ERR_ALERT | ERR_FATAL;
3214 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003215 }
3216
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003217 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3218 if (node) {
3219 struct proxy *target = container_of(node, struct proxy, conf.id);
3220 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3221 file, linenum, proxy_type_str(curproxy), curproxy->id,
3222 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3223 err_code |= ERR_ALERT | ERR_FATAL;
3224 goto out;
3225 }
3226 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003227 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003228 else if (!strcmp(args[0], "description")) {
3229 int i, len=0;
3230 char *d;
3231
Cyril Bonté99ed3272010-01-24 23:29:44 +01003232 if (curproxy == &defproxy) {
3233 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3234 file, linenum, args[0]);
3235 err_code |= ERR_ALERT | ERR_FATAL;
3236 goto out;
3237 }
3238
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003239 if (!*args[1]) {
3240 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3241 file, linenum, args[0]);
3242 return -1;
3243 }
3244
Willy Tarreau348acfe2014-04-14 15:00:39 +02003245 for (i = 1; *args[i]; i++)
3246 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003247
3248 d = (char *)calloc(1, len);
3249 curproxy->desc = d;
3250
Willy Tarreau348acfe2014-04-14 15:00:39 +02003251 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3252 for (i = 2; *args[i]; i++)
3253 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003254
3255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003256 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003257 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003259 curproxy->state = PR_STSTOPPED;
3260 }
3261 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003262 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3263 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003264 curproxy->state = PR_STNEW;
3265 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003266 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3267 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003268 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003269
3270 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003271 unsigned int low, high;
3272
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003273 if (strcmp(args[cur_arg], "all") == 0) {
3274 set = 0;
3275 break;
3276 }
3277 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003278 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003279 }
3280 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003281 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003282 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003283 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003284 char *dash = strchr(args[cur_arg], '-');
3285
3286 low = high = str2uic(args[cur_arg]);
3287 if (dash)
3288 high = str2uic(dash + 1);
3289
3290 if (high < low) {
3291 unsigned int swap = low;
3292 low = high;
3293 high = swap;
3294 }
3295
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003296 if (low < 1 || high > LONGBITS) {
3297 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3298 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003299 err_code |= ERR_ALERT | ERR_FATAL;
3300 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003301 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003302 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003303 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003304 }
3305 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003306 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3307 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003308 err_code |= ERR_ALERT | ERR_FATAL;
3309 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003310 }
3311 cur_arg++;
3312 }
3313 curproxy->bind_proc = set;
3314 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003315 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003316 if (curproxy == &defproxy) {
3317 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003320 }
3321
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003322 err = invalid_char(args[1]);
3323 if (err) {
3324 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3325 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003326 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003327 }
3328
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003329 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003330 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3331 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003332 err_code |= ERR_ALERT | ERR_FATAL;
3333 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003334 }
3335 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003336 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3337 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003338
Willy Tarreau977b8e42006-12-29 14:19:17 +01003339 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003340 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003341
Willy Tarreaubaaee002006-06-26 02:48:02 +02003342 if (*(args[1]) == 0) {
3343 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3344 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003345 err_code |= ERR_ALERT | ERR_FATAL;
3346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003348
Willy Tarreau67402132012-05-31 20:40:20 +02003349 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003350 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003351 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003352 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353 curproxy->cookie_name = strdup(args[1]);
3354 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003355
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 cur_arg = 2;
3357 while (*(args[cur_arg])) {
3358 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003359 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003360 }
3361 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003362 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 }
3364 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003365 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 }
3367 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003368 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369 }
3370 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003371 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003372 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003373 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003374 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003375 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003376 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003377 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003379 else if (!strcmp(args[cur_arg], "httponly")) {
3380 curproxy->ck_opts |= PR_CK_HTTPONLY;
3381 }
3382 else if (!strcmp(args[cur_arg], "secure")) {
3383 curproxy->ck_opts |= PR_CK_SECURE;
3384 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003385 else if (!strcmp(args[cur_arg], "domain")) {
3386 if (!*args[cur_arg + 1]) {
3387 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3388 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003391 }
3392
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003393 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003394 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003395 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3396 " dots nor does not start with a dot."
3397 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003398 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003399 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003400 }
3401
3402 err = invalid_domainchar(args[cur_arg + 1]);
3403 if (err) {
3404 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3405 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003408 }
3409
Willy Tarreau68a897b2009-12-03 23:28:34 +01003410 if (!curproxy->cookie_domain) {
3411 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3412 } else {
3413 /* one domain was already specified, add another one by
3414 * building the string which will be returned along with
3415 * the cookie.
3416 */
3417 char *new_ptr;
3418 int new_len = strlen(curproxy->cookie_domain) +
3419 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3420 new_ptr = malloc(new_len);
3421 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3422 free(curproxy->cookie_domain);
3423 curproxy->cookie_domain = new_ptr;
3424 }
Willy Tarreau31936852010-10-06 16:59:56 +02003425 cur_arg++;
3426 }
3427 else if (!strcmp(args[cur_arg], "maxidle")) {
3428 unsigned int maxidle;
3429 const char *res;
3430
3431 if (!*args[cur_arg + 1]) {
3432 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3433 file, linenum, args[cur_arg]);
3434 err_code |= ERR_ALERT | ERR_FATAL;
3435 goto out;
3436 }
3437
3438 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3439 if (res) {
3440 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3441 file, linenum, *res, args[cur_arg]);
3442 err_code |= ERR_ALERT | ERR_FATAL;
3443 goto out;
3444 }
3445 curproxy->cookie_maxidle = maxidle;
3446 cur_arg++;
3447 }
3448 else if (!strcmp(args[cur_arg], "maxlife")) {
3449 unsigned int maxlife;
3450 const char *res;
3451
3452 if (!*args[cur_arg + 1]) {
3453 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3454 file, linenum, args[cur_arg]);
3455 err_code |= ERR_ALERT | ERR_FATAL;
3456 goto out;
3457 }
3458
3459 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3460 if (res) {
3461 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3462 file, linenum, *res, args[cur_arg]);
3463 err_code |= ERR_ALERT | ERR_FATAL;
3464 goto out;
3465 }
3466 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003467 cur_arg++;
3468 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003469 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003470 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 +02003471 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003472 err_code |= ERR_ALERT | ERR_FATAL;
3473 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003474 }
3475 cur_arg++;
3476 }
Willy Tarreau67402132012-05-31 20:40:20 +02003477 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003478 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3479 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003480 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003481 }
3482
Willy Tarreau67402132012-05-31 20:40:20 +02003483 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003484 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3485 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003486 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003487 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003488
Willy Tarreau67402132012-05-31 20:40:20 +02003489 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003490 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3491 file, linenum);
3492 err_code |= ERR_ALERT | ERR_FATAL;
3493 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003494 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003495 else if (!strcmp(args[0], "email-alert")) {
3496 if (*(args[1]) == 0) {
3497 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3498 file, linenum, args[0]);
3499 err_code |= ERR_ALERT | ERR_FATAL;
3500 goto out;
3501 }
3502
3503 if (!strcmp(args[1], "from")) {
3504 if (*(args[1]) == 0) {
3505 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3506 file, linenum, args[1]);
3507 err_code |= ERR_ALERT | ERR_FATAL;
3508 goto out;
3509 }
3510 free(curproxy->email_alert.from);
3511 curproxy->email_alert.from = strdup(args[2]);
3512 }
3513 else if (!strcmp(args[1], "mailers")) {
3514 if (*(args[1]) == 0) {
3515 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3516 file, linenum, args[1]);
3517 err_code |= ERR_ALERT | ERR_FATAL;
3518 goto out;
3519 }
3520 free(curproxy->email_alert.mailers.name);
3521 curproxy->email_alert.mailers.name = strdup(args[2]);
3522 }
3523 else if (!strcmp(args[1], "myhostname")) {
3524 if (*(args[1]) == 0) {
3525 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3526 file, linenum, args[1]);
3527 err_code |= ERR_ALERT | ERR_FATAL;
3528 goto out;
3529 }
3530 free(curproxy->email_alert.myhostname);
3531 curproxy->email_alert.myhostname = strdup(args[2]);
3532 }
Simon Horman64e34162015-02-06 11:11:57 +09003533 else if (!strcmp(args[1], "level")) {
3534 curproxy->email_alert.level = get_log_level(args[2]);
3535 if (curproxy->email_alert.level < 0) {
3536 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3537 file, linenum, args[1], args[2]);
3538 err_code |= ERR_ALERT | ERR_FATAL;
3539 goto out;
3540 }
3541 }
Simon Horman9dc49962015-01-30 11:22:59 +09003542 else if (!strcmp(args[1], "to")) {
3543 if (*(args[1]) == 0) {
3544 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3545 file, linenum, args[1]);
3546 err_code |= ERR_ALERT | ERR_FATAL;
3547 goto out;
3548 }
3549 free(curproxy->email_alert.to);
3550 curproxy->email_alert.to = strdup(args[2]);
3551 }
3552 else {
3553 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3554 file, linenum, args[1]);
3555 err_code |= ERR_ALERT | ERR_FATAL;
3556 goto out;
3557 }
Simon Horman64e34162015-02-06 11:11:57 +09003558 /* Indicate that the email_alert is at least partially configured */
3559 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003560 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003561 else if (!strcmp(args[0], "external-check")) {
3562 if (*(args[1]) == 0) {
3563 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3564 file, linenum, args[0]);
3565 err_code |= ERR_ALERT | ERR_FATAL;
3566 goto out;
3567 }
3568
3569 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003570 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003571 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003572 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003573 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3574 file, linenum, args[1]);
3575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
3577 }
3578 free(curproxy->check_command);
3579 curproxy->check_command = strdup(args[2]);
3580 }
3581 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003582 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003583 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003584 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003585 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3586 file, linenum, args[1]);
3587 err_code |= ERR_ALERT | ERR_FATAL;
3588 goto out;
3589 }
3590 free(curproxy->check_path);
3591 curproxy->check_path = strdup(args[2]);
3592 }
3593 else {
3594 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3595 file, linenum, args[1]);
3596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
3598 }
3599 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003600 else if (!strcmp(args[0], "persist")) { /* persist */
3601 if (*(args[1]) == 0) {
3602 Alert("parsing [%s:%d] : missing persist method.\n",
3603 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003606 }
3607
3608 if (!strncmp(args[1], "rdp-cookie", 10)) {
3609 curproxy->options2 |= PR_O2_RDPC_PRST;
3610
Emeric Brunb982a3d2010-01-04 15:45:53 +01003611 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003612 const char *beg, *end;
3613
3614 beg = args[1] + 11;
3615 end = strchr(beg, ')');
3616
William Lallemanddf1425a2015-04-28 20:17:49 +02003617 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3618 goto out;
3619
Emeric Brun647caf12009-06-30 17:57:00 +02003620 if (!end || end == beg) {
3621 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3622 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003623 err_code |= ERR_ALERT | ERR_FATAL;
3624 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003625 }
3626
3627 free(curproxy->rdp_cookie_name);
3628 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3629 curproxy->rdp_cookie_len = end-beg;
3630 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003631 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003632 free(curproxy->rdp_cookie_name);
3633 curproxy->rdp_cookie_name = strdup("msts");
3634 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3635 }
3636 else { /* syntax */
3637 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3638 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003639 err_code |= ERR_ALERT | ERR_FATAL;
3640 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003641 }
3642 }
3643 else {
3644 Alert("parsing [%s:%d] : unknown persist method.\n",
3645 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003646 err_code |= ERR_ALERT | ERR_FATAL;
3647 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003648 }
3649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003650 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003651 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3652 err_code |= ERR_ALERT | ERR_FATAL;
3653 goto out;
3654 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003655 else if (!strcmp(args[0], "load-server-state-from-file")) {
3656 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3657 err_code |= ERR_WARN;
3658 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3659 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3660 }
3661 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3662 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3663 }
3664 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3665 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3666 }
3667 else {
3668 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3669 file, linenum, args[0], args[1]);
3670 err_code |= ERR_ALERT | ERR_FATAL;
3671 goto out;
3672 }
3673 }
3674 else if (!strcmp(args[0], "server-state-file-name")) {
3675 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3676 err_code |= ERR_WARN;
3677 if (*(args[1]) == 0) {
3678 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3679 file, linenum, args[0]);
3680 err_code |= ERR_ALERT | ERR_FATAL;
3681 goto out;
3682 }
3683 else if (!strcmp(args[1], "use-backend-name"))
3684 curproxy->server_state_file_name = strdup(curproxy->id);
3685 else
3686 curproxy->server_state_file_name = strdup(args[1]);
3687 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003688 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003689 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003690 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003691
Willy Tarreaubaaee002006-06-26 02:48:02 +02003692 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003693 if (curproxy == &defproxy) {
3694 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
3697 }
3698
William Lallemand1a748ae2015-05-19 16:37:23 +02003699 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3700 goto out;
3701
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702 if (*(args[4]) == 0) {
3703 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3704 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003705 err_code |= ERR_ALERT | ERR_FATAL;
3706 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003707 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003708 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003709 curproxy->capture_name = strdup(args[2]);
3710 curproxy->capture_namelen = strlen(curproxy->capture_name);
3711 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003712 curproxy->to_log |= LW_COOKIE;
3713 }
3714 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3715 struct cap_hdr *hdr;
3716
3717 if (curproxy == &defproxy) {
3718 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 +02003719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 }
3722
William Lallemand1a748ae2015-05-19 16:37:23 +02003723 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3724 goto out;
3725
Willy Tarreaubaaee002006-06-26 02:48:02 +02003726 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3727 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3728 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003729 err_code |= ERR_ALERT | ERR_FATAL;
3730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003731 }
3732
3733 hdr = calloc(sizeof(struct cap_hdr), 1);
3734 hdr->next = curproxy->req_cap;
3735 hdr->name = strdup(args[3]);
3736 hdr->namelen = strlen(args[3]);
3737 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003738 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003739 hdr->index = curproxy->nb_req_cap++;
3740 curproxy->req_cap = hdr;
3741 curproxy->to_log |= LW_REQHDR;
3742 }
3743 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3744 struct cap_hdr *hdr;
3745
3746 if (curproxy == &defproxy) {
3747 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 +02003748 err_code |= ERR_ALERT | ERR_FATAL;
3749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003750 }
3751
William Lallemand1a748ae2015-05-19 16:37:23 +02003752 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3753 goto out;
3754
Willy Tarreaubaaee002006-06-26 02:48:02 +02003755 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3756 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3757 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003758 err_code |= ERR_ALERT | ERR_FATAL;
3759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003760 }
3761 hdr = calloc(sizeof(struct cap_hdr), 1);
3762 hdr->next = curproxy->rsp_cap;
3763 hdr->name = strdup(args[3]);
3764 hdr->namelen = strlen(args[3]);
3765 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003766 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003767 hdr->index = curproxy->nb_rsp_cap++;
3768 curproxy->rsp_cap = hdr;
3769 curproxy->to_log |= LW_RSPHDR;
3770 }
3771 else {
3772 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3773 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003774 err_code |= ERR_ALERT | ERR_FATAL;
3775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776 }
3777 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003779 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003780 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003781
William Lallemanddf1425a2015-04-28 20:17:49 +02003782 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3783 goto out;
3784
Willy Tarreaubaaee002006-06-26 02:48:02 +02003785 if (*(args[1]) == 0) {
3786 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3787 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_ALERT | ERR_FATAL;
3789 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003790 }
3791 curproxy->conn_retries = atol(args[1]);
3792 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003793 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003794 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003795
3796 if (curproxy == &defproxy) {
3797 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3798 err_code |= ERR_ALERT | ERR_FATAL;
3799 goto out;
3800 }
3801
Willy Tarreau20b0de52012-12-24 15:45:22 +01003802 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003803 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003804 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3805 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3806 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3807 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003808 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 +01003809 file, linenum, args[0]);
3810 err_code |= ERR_WARN;
3811 }
3812
Willy Tarreauff011f22011-01-06 17:51:27 +01003813 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003814
Willy Tarreauff011f22011-01-06 17:51:27 +01003815 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003816 err_code |= ERR_ALERT | ERR_ABORT;
3817 goto out;
3818 }
3819
Willy Tarreau5002f572014-04-23 01:32:02 +02003820 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003821 err_code |= warnif_cond_conflicts(rule->cond,
3822 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3823 file, linenum);
3824
Willy Tarreauff011f22011-01-06 17:51:27 +01003825 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003826 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003827 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003828 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003829
3830 if (curproxy == &defproxy) {
3831 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
3834 }
3835
3836 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003837 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003838 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3839 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003840 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3841 file, linenum, args[0]);
3842 err_code |= ERR_WARN;
3843 }
3844
3845 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3846
3847 if (!rule) {
3848 err_code |= ERR_ALERT | ERR_ABORT;
3849 goto out;
3850 }
3851
3852 err_code |= warnif_cond_conflicts(rule->cond,
3853 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3854 file, linenum);
3855
3856 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3857 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003858 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3859 /* set the header name and length into the proxy structure */
3860 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3861 err_code |= ERR_WARN;
3862
3863 if (!*args[1]) {
3864 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3865 file, linenum, args[0]);
3866 err_code |= ERR_ALERT | ERR_FATAL;
3867 goto out;
3868 }
3869
3870 /* set the desired header name */
3871 free(curproxy->server_id_hdr_name);
3872 curproxy->server_id_hdr_name = strdup(args[1]);
3873 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3874 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003875 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003876 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003877
Willy Tarreaub099aca2008-10-12 17:26:37 +02003878 if (curproxy == &defproxy) {
3879 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003882 }
3883
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003884 /* emulate "block" using "http-request block". Since these rules are supposed to
3885 * be processed before all http-request rules, we put them into their own list
3886 * and will insert them at the end.
3887 */
3888 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3889 if (!rule) {
3890 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003891 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003892 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003893 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3894 err_code |= warnif_cond_conflicts(rule->cond,
3895 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3896 file, linenum);
3897 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003898
3899 if (!already_warned(WARN_BLOCK_DEPRECATED))
3900 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]);
3901
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003902 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003903 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003904 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003905
Cyril Bonté99ed3272010-01-24 23:29:44 +01003906 if (curproxy == &defproxy) {
3907 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3908 err_code |= ERR_ALERT | ERR_FATAL;
3909 goto out;
3910 }
3911
Willy Tarreaube4653b2015-05-28 15:26:58 +02003912 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003913 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3914 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003915 err_code |= ERR_ALERT | ERR_FATAL;
3916 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003917 }
3918
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003919 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003920 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003921 err_code |= warnif_cond_conflicts(rule->cond,
3922 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3923 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003924 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003925 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003926 struct switching_rule *rule;
3927
Willy Tarreaub099aca2008-10-12 17:26:37 +02003928 if (curproxy == &defproxy) {
3929 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003930 err_code |= ERR_ALERT | ERR_FATAL;
3931 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003932 }
3933
Willy Tarreau55ea7572007-06-17 19:56:27 +02003934 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003935 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003936
3937 if (*(args[1]) == 0) {
3938 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003941 }
3942
Willy Tarreauf51658d2014-04-23 01:21:56 +02003943 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3944 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3945 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3946 file, linenum, errmsg);
3947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
3949 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003950
Willy Tarreauf51658d2014-04-23 01:21:56 +02003951 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003952 }
3953
3954 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3955 rule->cond = cond;
3956 rule->be.name = strdup(args[1]);
3957 LIST_INIT(&rule->list);
3958 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3959 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003960 else if (strcmp(args[0], "use-server") == 0) {
3961 struct server_rule *rule;
3962
3963 if (curproxy == &defproxy) {
3964 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3965 err_code |= ERR_ALERT | ERR_FATAL;
3966 goto out;
3967 }
3968
3969 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3970 err_code |= ERR_WARN;
3971
3972 if (*(args[1]) == 0) {
3973 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3974 err_code |= ERR_ALERT | ERR_FATAL;
3975 goto out;
3976 }
3977
3978 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3979 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3980 file, linenum, args[0]);
3981 err_code |= ERR_ALERT | ERR_FATAL;
3982 goto out;
3983 }
3984
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003985 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3986 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3987 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
3990 }
3991
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003992 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003993
3994 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3995 rule->cond = cond;
3996 rule->srv.name = strdup(args[1]);
3997 LIST_INIT(&rule->list);
3998 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3999 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
4000 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004001 else if ((!strcmp(args[0], "force-persist")) ||
4002 (!strcmp(args[0], "ignore-persist"))) {
4003 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01004004
4005 if (curproxy == &defproxy) {
4006 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
4009 }
4010
4011 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
4012 err_code |= ERR_WARN;
4013
Willy Tarreauef6494c2010-01-28 17:12:36 +01004014 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01004015 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4016 file, linenum, args[0]);
4017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
4019 }
4020
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004021 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
4022 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
4023 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01004024 err_code |= ERR_ALERT | ERR_FATAL;
4025 goto out;
4026 }
4027
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004028 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
4029 * where force-persist is applied.
4030 */
4031 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01004032
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004033 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01004034 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004035 if (!strcmp(args[0], "force-persist")) {
4036 rule->type = PERSIST_TYPE_FORCE;
4037 } else {
4038 rule->type = PERSIST_TYPE_IGNORE;
4039 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004040 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004041 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004042 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004043 else if (!strcmp(args[0], "stick-table")) {
4044 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004045 struct proxy *other;
4046
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004047 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004048 if (other) {
4049 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4050 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4051 err_code |= ERR_ALERT | ERR_FATAL;
4052 goto out;
4053 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004054
Emeric Brun32da3c42010-09-23 18:39:19 +02004055 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004056 curproxy->table.type = (unsigned int)-1;
4057 while (*args[myidx]) {
4058 const char *err;
4059
4060 if (strcmp(args[myidx], "size") == 0) {
4061 myidx++;
4062 if (!*(args[myidx])) {
4063 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4064 file, linenum, args[myidx-1]);
4065 err_code |= ERR_ALERT | ERR_FATAL;
4066 goto out;
4067 }
4068 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4069 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4070 file, linenum, *err, args[myidx-1]);
4071 err_code |= ERR_ALERT | ERR_FATAL;
4072 goto out;
4073 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004074 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004075 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004076 else if (strcmp(args[myidx], "peers") == 0) {
4077 myidx++;
Godbach50523162013-12-11 19:48:57 +08004078 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004079 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4080 file, linenum, args[myidx-1]);
4081 err_code |= ERR_ALERT | ERR_FATAL;
4082 goto out;
Godbach50523162013-12-11 19:48:57 +08004083 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004084 curproxy->table.peers.name = strdup(args[myidx++]);
4085 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004086 else if (strcmp(args[myidx], "expire") == 0) {
4087 myidx++;
4088 if (!*(args[myidx])) {
4089 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4090 file, linenum, args[myidx-1]);
4091 err_code |= ERR_ALERT | ERR_FATAL;
4092 goto out;
4093 }
4094 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4095 if (err) {
4096 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4097 file, linenum, *err, args[myidx-1]);
4098 err_code |= ERR_ALERT | ERR_FATAL;
4099 goto out;
4100 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004101 if (val > INT_MAX) {
4102 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4103 file, linenum, val);
4104 err_code |= ERR_ALERT | ERR_FATAL;
4105 goto out;
4106 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004107 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004108 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004109 }
4110 else if (strcmp(args[myidx], "nopurge") == 0) {
4111 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004112 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004113 }
4114 else if (strcmp(args[myidx], "type") == 0) {
4115 myidx++;
4116 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4117 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4118 file, linenum, args[myidx]);
4119 err_code |= ERR_ALERT | ERR_FATAL;
4120 goto out;
4121 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004122 /* myidx already points to next arg */
4123 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004124 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004125 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004126 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004127
4128 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004129 nw = args[myidx];
4130 while (*nw) {
4131 /* the "store" keyword supports a comma-separated list */
4132 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004133 sa = NULL; /* store arg */
4134 while (*nw && *nw != ',') {
4135 if (*nw == '(') {
4136 *nw = 0;
4137 sa = ++nw;
4138 while (*nw != ')') {
4139 if (!*nw) {
4140 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4141 file, linenum, args[0], cw);
4142 err_code |= ERR_ALERT | ERR_FATAL;
4143 goto out;
4144 }
4145 nw++;
4146 }
4147 *nw = '\0';
4148 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004149 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004150 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004151 if (*nw)
4152 *nw++ = '\0';
4153 type = stktable_get_data_type(cw);
4154 if (type < 0) {
4155 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4156 file, linenum, args[0], cw);
4157 err_code |= ERR_ALERT | ERR_FATAL;
4158 goto out;
4159 }
Willy Tarreauac782882010-06-20 10:41:54 +02004160
4161 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4162 switch (err) {
4163 case PE_NONE: break;
4164 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004165 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4166 file, linenum, args[0], cw);
4167 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004168 break;
4169
4170 case PE_ARG_MISSING:
4171 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4172 file, linenum, args[0], cw);
4173 err_code |= ERR_ALERT | ERR_FATAL;
4174 goto out;
4175
4176 case PE_ARG_NOT_USED:
4177 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4178 file, linenum, args[0], cw);
4179 err_code |= ERR_ALERT | ERR_FATAL;
4180 goto out;
4181
4182 default:
4183 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4184 file, linenum, args[0], cw);
4185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004187 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004188 }
4189 myidx++;
4190 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004191 else {
4192 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4193 file, linenum, args[myidx]);
4194 err_code |= ERR_ALERT | ERR_FATAL;
4195 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004196 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004197 }
4198
4199 if (!curproxy->table.size) {
4200 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4201 file, linenum);
4202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
4204 }
4205
4206 if (curproxy->table.type == (unsigned int)-1) {
4207 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4208 file, linenum);
4209 err_code |= ERR_ALERT | ERR_FATAL;
4210 goto out;
4211 }
4212 }
4213 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004214 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004215 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004216 int myidx = 0;
4217 const char *name = NULL;
4218 int flags;
4219
4220 if (curproxy == &defproxy) {
4221 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
4224 }
4225
4226 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4227 err_code |= ERR_WARN;
4228 goto out;
4229 }
4230
4231 myidx++;
4232 if ((strcmp(args[myidx], "store") == 0) ||
4233 (strcmp(args[myidx], "store-request") == 0)) {
4234 myidx++;
4235 flags = STK_IS_STORE;
4236 }
4237 else if (strcmp(args[myidx], "store-response") == 0) {
4238 myidx++;
4239 flags = STK_IS_STORE | STK_ON_RSP;
4240 }
4241 else if (strcmp(args[myidx], "match") == 0) {
4242 myidx++;
4243 flags = STK_IS_MATCH;
4244 }
4245 else if (strcmp(args[myidx], "on") == 0) {
4246 myidx++;
4247 flags = STK_IS_MATCH | STK_IS_STORE;
4248 }
4249 else {
4250 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4251 err_code |= ERR_ALERT | ERR_FATAL;
4252 goto out;
4253 }
4254
4255 if (*(args[myidx]) == 0) {
4256 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
4259 }
4260
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004261 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004262 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004263 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004264 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
4267 }
4268
4269 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004270 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4271 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4272 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004273 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004274 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004275 goto out;
4276 }
4277 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004278 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4279 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4280 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004281 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004282 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004283 goto out;
4284 }
4285 }
4286
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004287 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004288 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004289
Emeric Brunb982a3d2010-01-04 15:45:53 +01004290 if (strcmp(args[myidx], "table") == 0) {
4291 myidx++;
4292 name = args[myidx++];
4293 }
4294
Willy Tarreauef6494c2010-01-28 17:12:36 +01004295 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004296 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4297 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4298 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004299 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004300 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004301 goto out;
4302 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004303 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004304 else if (*(args[myidx])) {
4305 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4306 file, linenum, args[0], args[myidx]);
4307 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004308 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004309 goto out;
4310 }
Emeric Brun97679e72010-09-23 17:56:44 +02004311 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004312 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004313 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004314 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004315
Emeric Brunb982a3d2010-01-04 15:45:53 +01004316 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4317 rule->cond = cond;
4318 rule->expr = expr;
4319 rule->flags = flags;
4320 rule->table.name = name ? strdup(name) : NULL;
4321 LIST_INIT(&rule->list);
4322 if (flags & STK_ON_RSP)
4323 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4324 else
4325 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4326 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004327 else if (!strcmp(args[0], "stats")) {
4328 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4329 curproxy->uri_auth = NULL; /* we must detach from the default config */
4330
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004331 if (!*args[1]) {
4332 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004333 } else if (!strcmp(args[1], "admin")) {
4334 struct stats_admin_rule *rule;
4335
4336 if (curproxy == &defproxy) {
4337 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4338 err_code |= ERR_ALERT | ERR_FATAL;
4339 goto out;
4340 }
4341
4342 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4343 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4344 err_code |= ERR_ALERT | ERR_ABORT;
4345 goto out;
4346 }
4347
4348 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4349 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4350 file, linenum, args[0], args[1]);
4351 err_code |= ERR_ALERT | ERR_FATAL;
4352 goto out;
4353 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004354 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4355 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4356 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004357 err_code |= ERR_ALERT | ERR_FATAL;
4358 goto out;
4359 }
4360
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004361 err_code |= warnif_cond_conflicts(cond,
4362 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4363 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004364
4365 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4366 rule->cond = cond;
4367 LIST_INIT(&rule->list);
4368 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004369 } else if (!strcmp(args[1], "uri")) {
4370 if (*(args[2]) == 0) {
4371 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004372 err_code |= ERR_ALERT | ERR_FATAL;
4373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004374 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4375 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004376 err_code |= ERR_ALERT | ERR_ABORT;
4377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004378 }
4379 } else if (!strcmp(args[1], "realm")) {
4380 if (*(args[2]) == 0) {
4381 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004382 err_code |= ERR_ALERT | ERR_FATAL;
4383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004384 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4385 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004386 err_code |= ERR_ALERT | ERR_ABORT;
4387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004388 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004389 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004390 unsigned interval;
4391
4392 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4393 if (err) {
4394 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4395 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004398 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4399 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004400 err_code |= ERR_ALERT | ERR_ABORT;
4401 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004402 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004403 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004404 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004405
4406 if (curproxy == &defproxy) {
4407 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4408 err_code |= ERR_ALERT | ERR_FATAL;
4409 goto out;
4410 }
4411
4412 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4413 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4414 err_code |= ERR_ALERT | ERR_ABORT;
4415 goto out;
4416 }
4417
Willy Tarreauff011f22011-01-06 17:51:27 +01004418 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004419 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004420 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4421 file, linenum, args[0]);
4422 err_code |= ERR_WARN;
4423 }
4424
Willy Tarreauff011f22011-01-06 17:51:27 +01004425 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004426
Willy Tarreauff011f22011-01-06 17:51:27 +01004427 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004428 err_code |= ERR_ALERT | ERR_ABORT;
4429 goto out;
4430 }
4431
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004432 err_code |= warnif_cond_conflicts(rule->cond,
4433 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4434 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004435 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004436
Willy Tarreaubaaee002006-06-26 02:48:02 +02004437 } else if (!strcmp(args[1], "auth")) {
4438 if (*(args[2]) == 0) {
4439 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004440 err_code |= ERR_ALERT | ERR_FATAL;
4441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004442 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4443 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004444 err_code |= ERR_ALERT | ERR_ABORT;
4445 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004446 }
4447 } else if (!strcmp(args[1], "scope")) {
4448 if (*(args[2]) == 0) {
4449 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004450 err_code |= ERR_ALERT | ERR_FATAL;
4451 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004452 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4453 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004454 err_code |= ERR_ALERT | ERR_ABORT;
4455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004456 }
4457 } else if (!strcmp(args[1], "enable")) {
4458 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4459 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004460 err_code |= ERR_ALERT | ERR_ABORT;
4461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004462 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004463 } else if (!strcmp(args[1], "hide-version")) {
4464 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4465 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004466 err_code |= ERR_ALERT | ERR_ABORT;
4467 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004468 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004469 } else if (!strcmp(args[1], "show-legends")) {
4470 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4471 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4472 err_code |= ERR_ALERT | ERR_ABORT;
4473 goto out;
4474 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004475 } else if (!strcmp(args[1], "show-node")) {
4476
4477 if (*args[2]) {
4478 int i;
4479 char c;
4480
4481 for (i=0; args[2][i]; i++) {
4482 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004483 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4484 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004485 break;
4486 }
4487
4488 if (!i || args[2][i]) {
4489 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4490 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4491 file, linenum, args[0], args[1]);
4492 err_code |= ERR_ALERT | ERR_FATAL;
4493 goto out;
4494 }
4495 }
4496
4497 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4498 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4499 err_code |= ERR_ALERT | ERR_ABORT;
4500 goto out;
4501 }
4502 } else if (!strcmp(args[1], "show-desc")) {
4503 char *desc = NULL;
4504
4505 if (*args[2]) {
4506 int i, len=0;
4507 char *d;
4508
Willy Tarreau348acfe2014-04-14 15:00:39 +02004509 for (i = 2; *args[i]; i++)
4510 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004511
4512 desc = d = (char *)calloc(1, len);
4513
Willy Tarreau348acfe2014-04-14 15:00:39 +02004514 d += snprintf(d, desc + len - d, "%s", args[2]);
4515 for (i = 3; *args[i]; i++)
4516 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004517 }
4518
4519 if (!*args[2] && !global.desc)
4520 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4521 file, linenum, args[1]);
4522 else {
4523 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4524 free(desc);
4525 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4526 err_code |= ERR_ALERT | ERR_ABORT;
4527 goto out;
4528 }
4529 free(desc);
4530 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004531 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004532stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004533 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 +01004534 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004535 err_code |= ERR_ALERT | ERR_FATAL;
4536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004537 }
4538 }
4539 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004540 int optnum;
4541
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004542 if (*(args[1]) == '\0') {
4543 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4544 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004545 err_code |= ERR_ALERT | ERR_FATAL;
4546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004547 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004548
4549 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4550 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004551 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4552 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4553 file, linenum, cfg_opts[optnum].name);
4554 err_code |= ERR_ALERT | ERR_FATAL;
4555 goto out;
4556 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004557 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4558 goto out;
4559
Willy Tarreau93893792009-07-23 13:19:11 +02004560 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4561 err_code |= ERR_WARN;
4562 goto out;
4563 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004564
Willy Tarreau3842f002009-06-14 11:39:52 +02004565 curproxy->no_options &= ~cfg_opts[optnum].val;
4566 curproxy->options &= ~cfg_opts[optnum].val;
4567
4568 switch (kwm) {
4569 case KWM_STD:
4570 curproxy->options |= cfg_opts[optnum].val;
4571 break;
4572 case KWM_NO:
4573 curproxy->no_options |= cfg_opts[optnum].val;
4574 break;
4575 case KWM_DEF: /* already cleared */
4576 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004577 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004578
Willy Tarreau93893792009-07-23 13:19:11 +02004579 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004580 }
4581 }
4582
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004583 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4584 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004585 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4586 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4587 file, linenum, cfg_opts2[optnum].name);
4588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
4590 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004591 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4592 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004593 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4594 err_code |= ERR_WARN;
4595 goto out;
4596 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004597
Willy Tarreau3842f002009-06-14 11:39:52 +02004598 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4599 curproxy->options2 &= ~cfg_opts2[optnum].val;
4600
4601 switch (kwm) {
4602 case KWM_STD:
4603 curproxy->options2 |= cfg_opts2[optnum].val;
4604 break;
4605 case KWM_NO:
4606 curproxy->no_options2 |= cfg_opts2[optnum].val;
4607 break;
4608 case KWM_DEF: /* already cleared */
4609 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004610 }
Willy Tarreau93893792009-07-23 13:19:11 +02004611 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004612 }
4613 }
4614
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004615 /* HTTP options override each other. They can be cancelled using
4616 * "no option xxx" which only switches to default mode if the mode
4617 * was this one (useful for cancelling options set in defaults
4618 * sections).
4619 */
4620 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004621 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4622 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004623 if (kwm == KWM_STD) {
4624 curproxy->options &= ~PR_O_HTTP_MODE;
4625 curproxy->options |= PR_O_HTTP_PCL;
4626 goto out;
4627 }
4628 else if (kwm == KWM_NO) {
4629 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4630 curproxy->options &= ~PR_O_HTTP_MODE;
4631 goto out;
4632 }
4633 }
4634 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004635 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4636 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004637 if (kwm == KWM_STD) {
4638 curproxy->options &= ~PR_O_HTTP_MODE;
4639 curproxy->options |= PR_O_HTTP_FCL;
4640 goto out;
4641 }
4642 else if (kwm == KWM_NO) {
4643 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4644 curproxy->options &= ~PR_O_HTTP_MODE;
4645 goto out;
4646 }
4647 }
4648 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004649 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4650 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004651 if (kwm == KWM_STD) {
4652 curproxy->options &= ~PR_O_HTTP_MODE;
4653 curproxy->options |= PR_O_HTTP_SCL;
4654 goto out;
4655 }
4656 else if (kwm == KWM_NO) {
4657 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4658 curproxy->options &= ~PR_O_HTTP_MODE;
4659 goto out;
4660 }
4661 }
4662 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004663 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4664 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004665 if (kwm == KWM_STD) {
4666 curproxy->options &= ~PR_O_HTTP_MODE;
4667 curproxy->options |= PR_O_HTTP_KAL;
4668 goto out;
4669 }
4670 else if (kwm == KWM_NO) {
4671 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4672 curproxy->options &= ~PR_O_HTTP_MODE;
4673 goto out;
4674 }
4675 }
4676 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004677 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4678 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004679 if (kwm == KWM_STD) {
4680 curproxy->options &= ~PR_O_HTTP_MODE;
4681 curproxy->options |= PR_O_HTTP_TUN;
4682 goto out;
4683 }
4684 else if (kwm == KWM_NO) {
4685 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4686 curproxy->options &= ~PR_O_HTTP_MODE;
4687 goto out;
4688 }
4689 }
4690
Joseph Lynch726ab712015-05-11 23:25:34 -07004691 /* Redispatch can take an integer argument that control when the
4692 * resispatch occurs. All values are relative to the retries option.
4693 * This can be cancelled using "no option xxx".
4694 */
4695 if (strcmp(args[1], "redispatch") == 0) {
4696 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4697 err_code |= ERR_WARN;
4698 goto out;
4699 }
4700
4701 curproxy->no_options &= ~PR_O_REDISP;
4702 curproxy->options &= ~PR_O_REDISP;
4703
4704 switch (kwm) {
4705 case KWM_STD:
4706 curproxy->options |= PR_O_REDISP;
4707 curproxy->redispatch_after = -1;
4708 if(*args[2]) {
4709 curproxy->redispatch_after = atol(args[2]);
4710 }
4711 break;
4712 case KWM_NO:
4713 curproxy->no_options |= PR_O_REDISP;
4714 curproxy->redispatch_after = 0;
4715 break;
4716 case KWM_DEF: /* already cleared */
4717 break;
4718 }
4719 goto out;
4720 }
4721
Willy Tarreau3842f002009-06-14 11:39:52 +02004722 if (kwm != KWM_STD) {
4723 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004724 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004725 err_code |= ERR_ALERT | ERR_FATAL;
4726 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004727 }
4728
Emeric Brun3a058f32009-06-30 18:26:00 +02004729 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004730 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004731 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004732 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004733 if (*(args[2]) != '\0') {
4734 if (!strcmp(args[2], "clf")) {
4735 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004736 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004737 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004738 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004739 err_code |= ERR_ALERT | ERR_FATAL;
4740 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004741 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004742 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4743 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004744 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004745 if (curproxy->conf.logformat_string != default_http_log_format &&
4746 curproxy->conf.logformat_string != default_tcp_log_format &&
4747 curproxy->conf.logformat_string != clf_http_log_format)
4748 free(curproxy->conf.logformat_string);
4749 curproxy->conf.logformat_string = logformat;
4750
4751 free(curproxy->conf.lfs_file);
4752 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4753 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004754 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004755 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004756 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004757 if (curproxy->conf.logformat_string != default_http_log_format &&
4758 curproxy->conf.logformat_string != default_tcp_log_format &&
4759 curproxy->conf.logformat_string != clf_http_log_format)
4760 free(curproxy->conf.logformat_string);
4761 curproxy->conf.logformat_string = default_tcp_log_format;
4762
4763 free(curproxy->conf.lfs_file);
4764 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4765 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004766
4767 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4768 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004769 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004770 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004771 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004772 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004773 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004774
William Lallemanddf1425a2015-04-28 20:17:49 +02004775 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4776 goto out;
4777
Willy Tarreau13943ab2006-12-31 00:24:10 +01004778 if (curproxy->cap & PR_CAP_FE)
4779 curproxy->options |= PR_O_TCP_CLI_KA;
4780 if (curproxy->cap & PR_CAP_BE)
4781 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004782 }
4783 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004784 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004785 err_code |= ERR_WARN;
4786
Willy Tarreaubaaee002006-06-26 02:48:02 +02004787 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004788 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004789 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004790 curproxy->options2 &= ~PR_O2_CHK_ANY;
4791 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004792 if (!*args[2]) { /* no argument */
4793 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4794 curproxy->check_len = strlen(DEF_CHECK_REQ);
4795 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004796 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004797 curproxy->check_req = (char *)malloc(reqlen);
4798 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004799 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004800 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004801 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004802 if (*args[4])
4803 reqlen += strlen(args[4]);
4804 else
4805 reqlen += strlen("HTTP/1.0");
4806
4807 curproxy->check_req = (char *)malloc(reqlen);
4808 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004809 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004810 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004811 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4812 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004813 }
4814 else if (!strcmp(args[1], "ssl-hello-chk")) {
4815 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004816 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004817 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004818
Willy Tarreaua534fea2008-08-03 12:19:50 +02004819 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004820 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004821 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004822 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004823
4824 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004826 }
Willy Tarreau23677902007-05-08 23:50:35 +02004827 else if (!strcmp(args[1], "smtpchk")) {
4828 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004829 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004830 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004831 curproxy->options2 &= ~PR_O2_CHK_ANY;
4832 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004833
4834 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4835 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4836 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4837 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4838 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4839 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4840 curproxy->check_req = (char *)malloc(reqlen);
4841 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4842 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4843 } else {
4844 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4845 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4846 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4847 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4848 }
4849 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004850 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4851 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004852 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004853 else if (!strcmp(args[1], "pgsql-check")) {
4854 /* use PostgreSQL request to check servers' health */
4855 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4856 err_code |= ERR_WARN;
4857
4858 free(curproxy->check_req);
4859 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004860 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004861 curproxy->options2 |= PR_O2_PGSQL_CHK;
4862
4863 if (*(args[2])) {
4864 int cur_arg = 2;
4865
4866 while (*(args[cur_arg])) {
4867 if (strcmp(args[cur_arg], "user") == 0) {
4868 char * packet;
4869 uint32_t packet_len;
4870 uint32_t pv;
4871
4872 /* suboption header - needs additional argument for it */
4873 if (*(args[cur_arg+1]) == 0) {
4874 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4875 file, linenum, args[0], args[1], args[cur_arg]);
4876 err_code |= ERR_ALERT | ERR_FATAL;
4877 goto out;
4878 }
4879
4880 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4881 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4882 pv = htonl(0x30000); /* protocol version 3.0 */
4883
4884 packet = (char*) calloc(1, packet_len);
4885
4886 memcpy(packet + 4, &pv, 4);
4887
4888 /* copy "user" */
4889 memcpy(packet + 8, "user", 4);
4890
4891 /* copy username */
4892 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4893
4894 free(curproxy->check_req);
4895 curproxy->check_req = packet;
4896 curproxy->check_len = packet_len;
4897
4898 packet_len = htonl(packet_len);
4899 memcpy(packet, &packet_len, 4);
4900 cur_arg += 2;
4901 } else {
4902 /* unknown suboption - catchall */
4903 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4904 file, linenum, args[0], args[1]);
4905 err_code |= ERR_ALERT | ERR_FATAL;
4906 goto out;
4907 }
4908 } /* end while loop */
4909 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004910 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4911 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004912 }
4913
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004914 else if (!strcmp(args[1], "redis-check")) {
4915 /* use REDIS PING request to check servers' health */
4916 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4917 err_code |= ERR_WARN;
4918
4919 free(curproxy->check_req);
4920 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004921 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004922 curproxy->options2 |= PR_O2_REDIS_CHK;
4923
4924 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4925 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4926 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004927
4928 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4929 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004930 }
4931
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004932 else if (!strcmp(args[1], "mysql-check")) {
4933 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004934 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4935 err_code |= ERR_WARN;
4936
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004937 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004938 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004939 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004940 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004941
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004942 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004943 * const char mysql40_client_auth_pkt[] = {
4944 * "\x0e\x00\x00" // packet length
4945 * "\x01" // packet number
4946 * "\x00\x00" // client capabilities
4947 * "\x00\x00\x01" // max packet
4948 * "haproxy\x00" // username (null terminated string)
4949 * "\x00" // filler (always 0x00)
4950 * "\x01\x00\x00" // packet length
4951 * "\x00" // packet number
4952 * "\x01" // COM_QUIT command
4953 * };
4954 */
4955
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004956 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4957 * const char mysql41_client_auth_pkt[] = {
4958 * "\x0e\x00\x00\" // packet length
4959 * "\x01" // packet number
4960 * "\x00\x00\x00\x00" // client capabilities
4961 * "\x00\x00\x00\x01" // max packet
4962 * "\x21" // character set (UTF-8)
4963 * char[23] // All zeroes
4964 * "haproxy\x00" // username (null terminated string)
4965 * "\x00" // filler (always 0x00)
4966 * "\x01\x00\x00" // packet length
4967 * "\x00" // packet number
4968 * "\x01" // COM_QUIT command
4969 * };
4970 */
4971
4972
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004973 if (*(args[2])) {
4974 int cur_arg = 2;
4975
4976 while (*(args[cur_arg])) {
4977 if (strcmp(args[cur_arg], "user") == 0) {
4978 char *mysqluser;
4979 int packetlen, reqlen, userlen;
4980
4981 /* suboption header - needs additional argument for it */
4982 if (*(args[cur_arg+1]) == 0) {
4983 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4984 file, linenum, args[0], args[1], args[cur_arg]);
4985 err_code |= ERR_ALERT | ERR_FATAL;
4986 goto out;
4987 }
4988 mysqluser = args[cur_arg + 1];
4989 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004990
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004991 if (*(args[cur_arg+2])) {
4992 if (!strcmp(args[cur_arg+2], "post-41")) {
4993 packetlen = userlen + 7 + 27;
4994 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004995
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004996 free(curproxy->check_req);
4997 curproxy->check_req = (char *)calloc(1, reqlen);
4998 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004999
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005000 snprintf(curproxy->check_req, 4, "%c%c%c",
5001 ((unsigned char) packetlen & 0xff),
5002 ((unsigned char) (packetlen >> 8) & 0xff),
5003 ((unsigned char) (packetlen >> 16) & 0xff));
5004
5005 curproxy->check_req[3] = 1;
5006 curproxy->check_req[5] = 130;
5007 curproxy->check_req[11] = 1;
5008 curproxy->check_req[12] = 33;
5009 memcpy(&curproxy->check_req[36], mysqluser, userlen);
5010 curproxy->check_req[36 + userlen + 1 + 1] = 1;
5011 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
5012 cur_arg += 3;
5013 } else {
5014 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
5015 err_code |= ERR_ALERT | ERR_FATAL;
5016 goto out;
5017 }
5018 } else {
5019 packetlen = userlen + 7;
5020 reqlen = packetlen + 9;
5021
5022 free(curproxy->check_req);
5023 curproxy->check_req = (char *)calloc(1, reqlen);
5024 curproxy->check_len = reqlen;
5025
5026 snprintf(curproxy->check_req, 4, "%c%c%c",
5027 ((unsigned char) packetlen & 0xff),
5028 ((unsigned char) (packetlen >> 8) & 0xff),
5029 ((unsigned char) (packetlen >> 16) & 0xff));
5030
5031 curproxy->check_req[3] = 1;
5032 curproxy->check_req[5] = 128;
5033 curproxy->check_req[8] = 1;
5034 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5035 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5036 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5037 cur_arg += 2;
5038 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005039 } else {
5040 /* unknown suboption - catchall */
5041 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5042 file, linenum, args[0], args[1]);
5043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
5045 }
5046 } /* end while loop */
5047 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005048 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005049 else if (!strcmp(args[1], "ldap-check")) {
5050 /* use LDAP request to check servers' health */
5051 free(curproxy->check_req);
5052 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005053 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005054 curproxy->options2 |= PR_O2_LDAP_CHK;
5055
5056 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
5057 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5058 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005059 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5060 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005061 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005062 else if (!strcmp(args[1], "tcp-check")) {
5063 /* use raw TCPCHK send/expect to check servers' health */
5064 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5065 err_code |= ERR_WARN;
5066
5067 free(curproxy->check_req);
5068 curproxy->check_req = NULL;
5069 curproxy->options2 &= ~PR_O2_CHK_ANY;
5070 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005071 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5072 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005073 }
Simon Horman98637e52014-06-20 12:30:16 +09005074 else if (!strcmp(args[1], "external-check")) {
5075 /* excute an external command to check servers' health */
5076 free(curproxy->check_req);
5077 curproxy->check_req = NULL;
5078 curproxy->options2 &= ~PR_O2_CHK_ANY;
5079 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005080 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5081 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005082 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005083 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005084 int cur_arg;
5085
5086 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5087 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005088 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005089
Willy Tarreau87cf5142011-08-19 22:57:24 +02005090 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005091
5092 free(curproxy->fwdfor_hdr_name);
5093 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5094 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5095
5096 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5097 cur_arg = 2;
5098 while (*(args[cur_arg])) {
5099 if (!strcmp(args[cur_arg], "except")) {
5100 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005101 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005102 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5103 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005104 err_code |= ERR_ALERT | ERR_FATAL;
5105 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005106 }
5107 /* flush useless bits */
5108 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005109 cur_arg += 2;
5110 } else if (!strcmp(args[cur_arg], "header")) {
5111 /* suboption header - needs additional argument for it */
5112 if (*(args[cur_arg+1]) == 0) {
5113 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5114 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005117 }
5118 free(curproxy->fwdfor_hdr_name);
5119 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5120 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5121 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005122 } else if (!strcmp(args[cur_arg], "if-none")) {
5123 curproxy->options &= ~PR_O_FF_ALWAYS;
5124 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005125 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005126 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005127 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005128 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005129 err_code |= ERR_ALERT | ERR_FATAL;
5130 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005131 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005132 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005133 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005134 else if (!strcmp(args[1], "originalto")) {
5135 int cur_arg;
5136
5137 /* insert x-original-to field, but not for the IP address listed as an except.
5138 * set default options (ie: bitfield, header name, etc)
5139 */
5140
5141 curproxy->options |= PR_O_ORGTO;
5142
5143 free(curproxy->orgto_hdr_name);
5144 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5145 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5146
Willy Tarreau87cf5142011-08-19 22:57:24 +02005147 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005148 cur_arg = 2;
5149 while (*(args[cur_arg])) {
5150 if (!strcmp(args[cur_arg], "except")) {
5151 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005152 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 +02005153 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5154 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005155 err_code |= ERR_ALERT | ERR_FATAL;
5156 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005157 }
5158 /* flush useless bits */
5159 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5160 cur_arg += 2;
5161 } else if (!strcmp(args[cur_arg], "header")) {
5162 /* suboption header - needs additional argument for it */
5163 if (*(args[cur_arg+1]) == 0) {
5164 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5165 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005166 err_code |= ERR_ALERT | ERR_FATAL;
5167 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005168 }
5169 free(curproxy->orgto_hdr_name);
5170 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5171 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5172 cur_arg += 2;
5173 } else {
5174 /* unknown suboption - catchall */
5175 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5176 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005177 err_code |= ERR_ALERT | ERR_FATAL;
5178 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005179 }
5180 } /* end while loop */
5181 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005182 else {
5183 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005184 err_code |= ERR_ALERT | ERR_FATAL;
5185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005186 }
Willy Tarreau93893792009-07-23 13:19:11 +02005187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005188 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005189 else if (!strcmp(args[0], "default_backend")) {
5190 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005191 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005192
5193 if (*(args[1]) == 0) {
5194 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005195 err_code |= ERR_ALERT | ERR_FATAL;
5196 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005197 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005198 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005199 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005200
5201 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5202 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005203 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005204 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005205 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005206 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005207
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005208 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5209 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 +01005210 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005211 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005212 /* enable reconnections to dispatch */
5213 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005214
5215 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005217 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005218 else if (!strcmp(args[0], "http-reuse")) {
5219 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5220 err_code |= ERR_WARN;
5221
5222 if (strcmp(args[1], "never") == 0) {
5223 /* enable a graceful server shutdown on an HTTP 404 response */
5224 curproxy->options &= ~PR_O_REUSE_MASK;
5225 curproxy->options |= PR_O_REUSE_NEVR;
5226 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5227 goto out;
5228 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005229 else if (strcmp(args[1], "safe") == 0) {
5230 /* enable a graceful server shutdown on an HTTP 404 response */
5231 curproxy->options &= ~PR_O_REUSE_MASK;
5232 curproxy->options |= PR_O_REUSE_SAFE;
5233 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5234 goto out;
5235 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005236 else if (strcmp(args[1], "aggressive") == 0) {
5237 curproxy->options &= ~PR_O_REUSE_MASK;
5238 curproxy->options |= PR_O_REUSE_AGGR;
5239 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5240 goto out;
5241 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005242 else if (strcmp(args[1], "always") == 0) {
5243 /* enable a graceful server shutdown on an HTTP 404 response */
5244 curproxy->options &= ~PR_O_REUSE_MASK;
5245 curproxy->options |= PR_O_REUSE_ALWS;
5246 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5247 goto out;
5248 }
5249 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005250 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005251 err_code |= ERR_ALERT | ERR_FATAL;
5252 goto out;
5253 }
5254 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005255 else if (!strcmp(args[0], "http-check")) {
5256 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005257 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005258
5259 if (strcmp(args[1], "disable-on-404") == 0) {
5260 /* enable a graceful server shutdown on an HTTP 404 response */
5261 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005262 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5263 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005264 }
Willy Tarreauef781042010-01-27 11:53:01 +01005265 else if (strcmp(args[1], "send-state") == 0) {
5266 /* enable emission of the apparent state of a server in HTTP checks */
5267 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005268 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5269 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005270 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005271 else if (strcmp(args[1], "expect") == 0) {
5272 const char *ptr_arg;
5273 int cur_arg;
5274
5275 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5276 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5277 err_code |= ERR_ALERT | ERR_FATAL;
5278 goto out;
5279 }
5280
5281 cur_arg = 2;
5282 /* consider exclamation marks, sole or at the beginning of a word */
5283 while (*(ptr_arg = args[cur_arg])) {
5284 while (*ptr_arg == '!') {
5285 curproxy->options2 ^= PR_O2_EXP_INV;
5286 ptr_arg++;
5287 }
5288 if (*ptr_arg)
5289 break;
5290 cur_arg++;
5291 }
5292 /* now ptr_arg points to the beginning of a word past any possible
5293 * exclamation mark, and cur_arg is the argument which holds this word.
5294 */
5295 if (strcmp(ptr_arg, "status") == 0) {
5296 if (!*(args[cur_arg + 1])) {
5297 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5298 file, linenum, args[0], args[1], ptr_arg);
5299 err_code |= ERR_ALERT | ERR_FATAL;
5300 goto out;
5301 }
5302 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005303 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005304 curproxy->expect_str = strdup(args[cur_arg + 1]);
5305 }
5306 else if (strcmp(ptr_arg, "string") == 0) {
5307 if (!*(args[cur_arg + 1])) {
5308 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5309 file, linenum, args[0], args[1], ptr_arg);
5310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
5312 }
5313 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005314 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005315 curproxy->expect_str = strdup(args[cur_arg + 1]);
5316 }
5317 else if (strcmp(ptr_arg, "rstatus") == 0) {
5318 if (!*(args[cur_arg + 1])) {
5319 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5320 file, linenum, args[0], args[1], ptr_arg);
5321 err_code |= ERR_ALERT | ERR_FATAL;
5322 goto out;
5323 }
5324 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005325 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005326 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005327 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005328 free(curproxy->expect_regex);
5329 curproxy->expect_regex = NULL;
5330 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005331 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005332 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5333 error = NULL;
5334 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5335 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5336 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5337 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005338 err_code |= ERR_ALERT | ERR_FATAL;
5339 goto out;
5340 }
5341 }
5342 else if (strcmp(ptr_arg, "rstring") == 0) {
5343 if (!*(args[cur_arg + 1])) {
5344 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5345 file, linenum, args[0], args[1], ptr_arg);
5346 err_code |= ERR_ALERT | ERR_FATAL;
5347 goto out;
5348 }
5349 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005350 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005351 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005352 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005353 free(curproxy->expect_regex);
5354 curproxy->expect_regex = NULL;
5355 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005356 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005357 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5358 error = NULL;
5359 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5360 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5361 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5362 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005363 err_code |= ERR_ALERT | ERR_FATAL;
5364 goto out;
5365 }
5366 }
5367 else {
5368 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5369 file, linenum, args[0], args[1], ptr_arg);
5370 err_code |= ERR_ALERT | ERR_FATAL;
5371 goto out;
5372 }
5373 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005374 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005375 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 +02005376 err_code |= ERR_ALERT | ERR_FATAL;
5377 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005378 }
5379 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005380 else if (!strcmp(args[0], "tcp-check")) {
5381 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5382 err_code |= ERR_WARN;
5383
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005384 if (strcmp(args[1], "comment") == 0) {
5385 int cur_arg;
5386 struct tcpcheck_rule *tcpcheck;
5387
5388 cur_arg = 1;
5389 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5390 tcpcheck->action = TCPCHK_ACT_COMMENT;
5391
5392 if (!*args[cur_arg + 1]) {
5393 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5394 file, linenum, args[cur_arg]);
5395 err_code |= ERR_ALERT | ERR_FATAL;
5396 goto out;
5397 }
5398
5399 tcpcheck->comment = strdup(args[cur_arg + 1]);
5400
5401 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005402 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5403 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005404 }
5405 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005406 const char *ptr_arg;
5407 int cur_arg;
5408 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005409
5410 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005411 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5412 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5413 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5414 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5415 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005416
Willy Tarreau5581c272015-05-13 12:24:53 +02005417 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5418 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5419 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5420 file, linenum);
5421 err_code |= ERR_ALERT | ERR_FATAL;
5422 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005423 }
5424
5425 cur_arg = 2;
5426 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5427 tcpcheck->action = TCPCHK_ACT_CONNECT;
5428
5429 /* parsing each parameters to fill up the rule */
5430 while (*(ptr_arg = args[cur_arg])) {
5431 /* tcp port */
5432 if (strcmp(args[cur_arg], "port") == 0) {
5433 if ( (atol(args[cur_arg + 1]) > 65535) ||
5434 (atol(args[cur_arg + 1]) < 1) ){
5435 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5436 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5437 err_code |= ERR_ALERT | ERR_FATAL;
5438 goto out;
5439 }
5440 tcpcheck->port = atol(args[cur_arg + 1]);
5441 cur_arg += 2;
5442 }
5443 /* send proxy protocol */
5444 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5445 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5446 cur_arg++;
5447 }
5448#ifdef USE_OPENSSL
5449 else if (strcmp(args[cur_arg], "ssl") == 0) {
5450 curproxy->options |= PR_O_TCPCHK_SSL;
5451 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5452 cur_arg++;
5453 }
5454#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005455 /* comment for this tcpcheck line */
5456 else if (strcmp(args[cur_arg], "comment") == 0) {
5457 if (!*args[cur_arg + 1]) {
5458 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5459 file, linenum, args[cur_arg]);
5460 err_code |= ERR_ALERT | ERR_FATAL;
5461 goto out;
5462 }
5463 tcpcheck->comment = strdup(args[cur_arg + 1]);
5464 cur_arg += 2;
5465 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005466 else {
5467#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005468 Alert("parsing [%s:%d] : '%s %s' expects 'comment', 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005469#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005470 Alert("parsing [%s:%d] : '%s %s' expects 'comment', 'port', 'send-proxy' or but got '%s' as argument.\n",
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005471#endif /* USE_OPENSSL */
5472 file, linenum, args[0], args[1], args[cur_arg]);
5473 err_code |= ERR_ALERT | ERR_FATAL;
5474 goto out;
5475 }
5476
5477 }
5478
5479 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5480 }
5481 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005482 if (! *(args[2]) ) {
5483 /* SEND string expected */
5484 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5485 file, linenum, args[0], args[1], args[2]);
5486 err_code |= ERR_ALERT | ERR_FATAL;
5487 goto out;
5488 } else {
5489 struct tcpcheck_rule *tcpcheck;
5490
5491 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5492
5493 tcpcheck->action = TCPCHK_ACT_SEND;
5494 tcpcheck->string_len = strlen(args[2]);
5495 tcpcheck->string = strdup(args[2]);
5496 tcpcheck->expect_regex = NULL;
5497
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005498 /* comment for this tcpcheck line */
5499 if (strcmp(args[3], "comment") == 0) {
5500 if (!*args[4]) {
5501 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5502 file, linenum, args[3]);
5503 err_code |= ERR_ALERT | ERR_FATAL;
5504 goto out;
5505 }
5506 tcpcheck->comment = strdup(args[4]);
5507 }
5508
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005509 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5510 }
5511 }
5512 else if (strcmp(args[1], "send-binary") == 0) {
5513 if (! *(args[2]) ) {
5514 /* SEND binary string expected */
5515 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5516 file, linenum, args[0], args[1], args[2]);
5517 err_code |= ERR_ALERT | ERR_FATAL;
5518 goto out;
5519 } else {
5520 struct tcpcheck_rule *tcpcheck;
5521 char *err = NULL;
5522
5523 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5524
5525 tcpcheck->action = TCPCHK_ACT_SEND;
5526 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5527 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5528 file, linenum, args[0], args[1], args[2], err);
5529 err_code |= ERR_ALERT | ERR_FATAL;
5530 goto out;
5531 }
5532 tcpcheck->expect_regex = NULL;
5533
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005534 /* comment for this tcpcheck line */
5535 if (strcmp(args[3], "comment") == 0) {
5536 if (!*args[4]) {
5537 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5538 file, linenum, args[3]);
5539 err_code |= ERR_ALERT | ERR_FATAL;
5540 goto out;
5541 }
5542 tcpcheck->comment = strdup(args[4]);
5543 }
5544
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005545 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5546 }
5547 }
5548 else if (strcmp(args[1], "expect") == 0) {
5549 const char *ptr_arg;
5550 int cur_arg;
5551 int inverse = 0;
5552
5553 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5554 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5555 err_code |= ERR_ALERT | ERR_FATAL;
5556 goto out;
5557 }
5558
5559 cur_arg = 2;
5560 /* consider exclamation marks, sole or at the beginning of a word */
5561 while (*(ptr_arg = args[cur_arg])) {
5562 while (*ptr_arg == '!') {
5563 inverse = !inverse;
5564 ptr_arg++;
5565 }
5566 if (*ptr_arg)
5567 break;
5568 cur_arg++;
5569 }
5570 /* now ptr_arg points to the beginning of a word past any possible
5571 * exclamation mark, and cur_arg is the argument which holds this word.
5572 */
5573 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005574 struct tcpcheck_rule *tcpcheck;
5575 char *err = NULL;
5576
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005577 if (!*(args[cur_arg + 1])) {
5578 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5579 file, linenum, args[0], args[1], ptr_arg);
5580 err_code |= ERR_ALERT | ERR_FATAL;
5581 goto out;
5582 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005583
5584 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5585
5586 tcpcheck->action = TCPCHK_ACT_EXPECT;
5587 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5588 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5589 file, linenum, args[0], args[1], args[2], err);
5590 err_code |= ERR_ALERT | ERR_FATAL;
5591 goto out;
5592 }
5593 tcpcheck->expect_regex = NULL;
5594 tcpcheck->inverse = inverse;
5595
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005596 /* tcpcheck comment */
5597 cur_arg += 2;
5598 if (strcmp(args[cur_arg], "comment") == 0) {
5599 if (!*args[cur_arg + 1]) {
5600 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5601 file, linenum, args[cur_arg + 1]);
5602 err_code |= ERR_ALERT | ERR_FATAL;
5603 goto out;
5604 }
5605 tcpcheck->comment = strdup(args[cur_arg + 1]);
5606 }
5607
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005608 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5609 }
5610 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005611 struct tcpcheck_rule *tcpcheck;
5612
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005613 if (!*(args[cur_arg + 1])) {
5614 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5615 file, linenum, args[0], args[1], ptr_arg);
5616 err_code |= ERR_ALERT | ERR_FATAL;
5617 goto out;
5618 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005619
5620 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5621
5622 tcpcheck->action = TCPCHK_ACT_EXPECT;
5623 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5624 tcpcheck->string = strdup(args[cur_arg + 1]);
5625 tcpcheck->expect_regex = NULL;
5626 tcpcheck->inverse = inverse;
5627
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005628 /* tcpcheck comment */
5629 cur_arg += 2;
5630 if (strcmp(args[cur_arg], "comment") == 0) {
5631 if (!*args[cur_arg + 1]) {
5632 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5633 file, linenum, args[cur_arg + 1]);
5634 err_code |= ERR_ALERT | ERR_FATAL;
5635 goto out;
5636 }
5637 tcpcheck->comment = strdup(args[cur_arg + 1]);
5638 }
5639
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005640 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5641 }
5642 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005643 struct tcpcheck_rule *tcpcheck;
5644
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005645 if (!*(args[cur_arg + 1])) {
5646 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5647 file, linenum, args[0], args[1], ptr_arg);
5648 err_code |= ERR_ALERT | ERR_FATAL;
5649 goto out;
5650 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005651
5652 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5653
5654 tcpcheck->action = TCPCHK_ACT_EXPECT;
5655 tcpcheck->string_len = 0;
5656 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005657 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5658 error = NULL;
5659 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5660 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5661 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5662 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005663 err_code |= ERR_ALERT | ERR_FATAL;
5664 goto out;
5665 }
5666 tcpcheck->inverse = inverse;
5667
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005668 /* tcpcheck comment */
5669 cur_arg += 2;
5670 if (strcmp(args[cur_arg], "comment") == 0) {
5671 if (!*args[cur_arg + 1]) {
5672 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5673 file, linenum, args[cur_arg + 1]);
5674 err_code |= ERR_ALERT | ERR_FATAL;
5675 goto out;
5676 }
5677 tcpcheck->comment = strdup(args[cur_arg + 1]);
5678 }
5679
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005680 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5681 }
5682 else {
5683 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5684 file, linenum, args[0], args[1], ptr_arg);
5685 err_code |= ERR_ALERT | ERR_FATAL;
5686 goto out;
5687 }
5688 }
5689 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005690 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005691 err_code |= ERR_ALERT | ERR_FATAL;
5692 goto out;
5693 }
5694 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005695 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005696 if (curproxy == &defproxy) {
5697 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005698 err_code |= ERR_ALERT | ERR_FATAL;
5699 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005700 }
5701
Willy Tarreaub80c2302007-11-30 20:51:32 +01005702 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005703 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005704
5705 if (strcmp(args[1], "fail") == 0) {
5706 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005707 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005708 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5709 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005710 err_code |= ERR_ALERT | ERR_FATAL;
5711 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005712 }
5713
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005714 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5715 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5716 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005717 err_code |= ERR_ALERT | ERR_FATAL;
5718 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005719 }
5720 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5721 }
5722 else {
5723 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005724 err_code |= ERR_ALERT | ERR_FATAL;
5725 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005726 }
5727 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005728#ifdef TPROXY
5729 else if (!strcmp(args[0], "transparent")) {
5730 /* enable transparent proxy connections */
5731 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005732 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005734 }
5735#endif
5736 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005737 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005738 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005739
Willy Tarreaubaaee002006-06-26 02:48:02 +02005740 if (*(args[1]) == 0) {
5741 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005742 err_code |= ERR_ALERT | ERR_FATAL;
5743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005744 }
5745 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005746 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5747 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005748 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005749 else if (!strcmp(args[0], "backlog")) { /* backlog */
5750 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005751 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005752
5753 if (*(args[1]) == 0) {
5754 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005755 err_code |= ERR_ALERT | ERR_FATAL;
5756 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005757 }
5758 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005759 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5760 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005761 }
Willy Tarreau86034312006-12-29 00:10:33 +01005762 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005763 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005764 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005765
Willy Tarreau86034312006-12-29 00:10:33 +01005766 if (*(args[1]) == 0) {
5767 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005768 err_code |= ERR_ALERT | ERR_FATAL;
5769 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005770 }
5771 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005772 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5773 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005774 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005775 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5776 if (*(args[1]) == 0) {
5777 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005778 err_code |= ERR_ALERT | ERR_FATAL;
5779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005780 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005781 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5782 if (err) {
5783 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5784 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005785 err_code |= ERR_ALERT | ERR_FATAL;
5786 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005787 }
5788 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005789 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005791 }
5792 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005793 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005794 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005795 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005796
Willy Tarreaubaaee002006-06-26 02:48:02 +02005797 if (curproxy == &defproxy) {
5798 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005799 err_code |= ERR_ALERT | ERR_FATAL;
5800 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005801 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005802 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005803 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005804
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005805 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005806 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005807 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005808 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005809 goto out;
5810 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005811
5812 proto = protocol_by_family(sk->ss_family);
5813 if (!proto || !proto->connect) {
5814 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5815 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005816 err_code |= ERR_ALERT | ERR_FATAL;
5817 goto out;
5818 }
5819
5820 if (port1 != port2) {
5821 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5822 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005823 err_code |= ERR_ALERT | ERR_FATAL;
5824 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005825 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005826
5827 if (!port1) {
5828 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5829 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005830 err_code |= ERR_ALERT | ERR_FATAL;
5831 goto out;
5832 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005833
William Lallemanddf1425a2015-04-28 20:17:49 +02005834 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5835 goto out;
5836
Willy Tarreaud5191e72010-02-09 20:50:45 +01005837 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005838 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005839 }
5840 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005841 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005842 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005843
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005844 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5845 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005846 err_code |= ERR_ALERT | ERR_FATAL;
5847 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005848 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005849 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005850 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005851 /**
5852 * The syntax for hash-type config element is
5853 * hash-type {map-based|consistent} [[<algo>] avalanche]
5854 *
5855 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5856 */
5857 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005858
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005859 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5860 err_code |= ERR_WARN;
5861
5862 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005863 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5864 }
5865 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005866 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5867 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005868 else if (strcmp(args[1], "avalanche") == 0) {
5869 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]);
5870 err_code |= ERR_ALERT | ERR_FATAL;
5871 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005872 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005873 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005874 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005875 err_code |= ERR_ALERT | ERR_FATAL;
5876 goto out;
5877 }
Bhaskar98634f02013-10-29 23:30:51 -04005878
5879 /* set the hash function to use */
5880 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005881 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005882 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005883
5884 /* if consistent with no argument, then avalanche modifier is also applied */
5885 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5886 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005887 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005888 /* set the hash function */
5889 if (!strcmp(args[2], "sdbm")) {
5890 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5891 }
5892 else if (!strcmp(args[2], "djb2")) {
5893 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005894 }
5895 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005896 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005897 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005898 else if (!strcmp(args[2], "crc32")) {
5899 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5900 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005901 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005902 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 -05005903 err_code |= ERR_ALERT | ERR_FATAL;
5904 goto out;
5905 }
5906
5907 /* set the hash modifier */
5908 if (!strcmp(args[3], "avalanche")) {
5909 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5910 }
5911 else if (*args[3]) {
5912 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5913 err_code |= ERR_ALERT | ERR_FATAL;
5914 goto out;
5915 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005916 }
William Lallemanda73203e2012-03-12 12:48:57 +01005917 }
William Lallemanda73203e2012-03-12 12:48:57 +01005918 else if (strcmp(args[0], "unique-id-format") == 0) {
5919 if (!*(args[1])) {
5920 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5921 err_code |= ERR_ALERT | ERR_FATAL;
5922 goto out;
5923 }
William Lallemand3203ff42012-11-11 17:30:56 +01005924 if (*(args[2])) {
5925 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5926 err_code |= ERR_ALERT | ERR_FATAL;
5927 goto out;
5928 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005929 free(curproxy->conf.uniqueid_format_string);
5930 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005931
Willy Tarreau62a61232013-04-12 18:13:46 +02005932 free(curproxy->conf.uif_file);
5933 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5934 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005935 }
William Lallemanda73203e2012-03-12 12:48:57 +01005936
5937 else if (strcmp(args[0], "unique-id-header") == 0) {
5938 if (!*(args[1])) {
5939 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5940 err_code |= ERR_ALERT | ERR_FATAL;
5941 goto out;
5942 }
5943 free(curproxy->header_unique_id);
5944 curproxy->header_unique_id = strdup(args[1]);
5945 }
5946
William Lallemand723b73a2012-02-08 16:37:49 +01005947 else if (strcmp(args[0], "log-format") == 0) {
5948 if (!*(args[1])) {
5949 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5950 err_code |= ERR_ALERT | ERR_FATAL;
5951 goto out;
5952 }
William Lallemand3203ff42012-11-11 17:30:56 +01005953 if (*(args[2])) {
5954 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5955 err_code |= ERR_ALERT | ERR_FATAL;
5956 goto out;
5957 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005958
Willy Tarreau62a61232013-04-12 18:13:46 +02005959 if (curproxy->conf.logformat_string != default_http_log_format &&
5960 curproxy->conf.logformat_string != default_tcp_log_format &&
5961 curproxy->conf.logformat_string != clf_http_log_format)
5962 free(curproxy->conf.logformat_string);
5963 curproxy->conf.logformat_string = strdup(args[1]);
5964
5965 free(curproxy->conf.lfs_file);
5966 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5967 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005968
5969 /* get a chance to improve log-format error reporting by
5970 * reporting the correct line-number when possible.
5971 */
5972 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5973 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5974 file, linenum, curproxy->id);
5975 err_code |= ERR_WARN;
5976 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005977 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005978 else if (!strcmp(args[0], "log-format-sd")) {
5979 if (!*(args[1])) {
5980 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5981 err_code |= ERR_ALERT | ERR_FATAL;
5982 goto out;
5983 }
5984 if (*(args[2])) {
5985 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5986 err_code |= ERR_ALERT | ERR_FATAL;
5987 goto out;
5988 }
5989
5990 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5991 free(curproxy->conf.logformat_sd_string);
5992 curproxy->conf.logformat_sd_string = strdup(args[1]);
5993
5994 free(curproxy->conf.lfsd_file);
5995 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5996 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5997
5998 /* get a chance to improve log-format-sd error reporting by
5999 * reporting the correct line-number when possible.
6000 */
6001 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6002 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6003 file, linenum, curproxy->id);
6004 err_code |= ERR_WARN;
6005 }
6006 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006007 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6008 if (*(args[1]) == 0) {
6009 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6010 err_code |= ERR_ALERT | ERR_FATAL;
6011 goto out;
6012 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006013 chunk_destroy(&curproxy->log_tag);
6014 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006015 }
William Lallemand0f99e342011-10-12 17:50:54 +02006016 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6017 /* delete previous herited or defined syslog servers */
6018 struct logsrv *back;
6019
6020 if (*(args[1]) != 0) {
6021 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6022 err_code |= ERR_ALERT | ERR_FATAL;
6023 goto out;
6024 }
6025
William Lallemand723b73a2012-02-08 16:37:49 +01006026 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6027 LIST_DEL(&tmplogsrv->list);
6028 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006029 }
6030 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006031 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006032 struct logsrv *logsrv;
6033
Willy Tarreaubaaee002006-06-26 02:48:02 +02006034 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006035 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006036 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02006037 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01006038 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006039 LIST_INIT(&node->list);
6040 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6041 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006042 }
6043 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006044 struct sockaddr_storage *sk;
6045 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006046 int arg = 0;
6047 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006048
6049 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006050
Willy Tarreau18324f52014-06-27 18:10:07 +02006051 /* just after the address, a length may be specified */
6052 if (strcmp(args[arg+2], "len") == 0) {
6053 len = atoi(args[arg+3]);
6054 if (len < 80 || len > 65535) {
6055 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6056 file, linenum, args[arg+3]);
6057 err_code |= ERR_ALERT | ERR_FATAL;
6058 goto out;
6059 }
6060 logsrv->maxlen = len;
6061
6062 /* skip these two args */
6063 arg += 2;
6064 }
6065 else
6066 logsrv->maxlen = MAX_SYSLOG_LEN;
6067
6068 if (logsrv->maxlen > global.max_syslog_len) {
6069 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02006070 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02006071 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006072 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006073 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006074 }
6075
Dragan Dosen1322d092015-09-22 16:05:32 +02006076 /* after the length, a format may be specified */
6077 if (strcmp(args[arg+2], "format") == 0) {
6078 logsrv->format = get_log_format(args[arg+3]);
6079 if (logsrv->format < 0) {
6080 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6081 err_code |= ERR_ALERT | ERR_FATAL;
6082 goto out;
6083 }
6084
6085 /* skip these two args */
6086 arg += 2;
6087 }
6088
William Lallemanddf1425a2015-04-28 20:17:49 +02006089 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6090 goto out;
6091
Willy Tarreau18324f52014-06-27 18:10:07 +02006092 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006093 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006094 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006095 err_code |= ERR_ALERT | ERR_FATAL;
6096 goto out;
6097
Willy Tarreaubaaee002006-06-26 02:48:02 +02006098 }
6099
William Lallemand0f99e342011-10-12 17:50:54 +02006100 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006101 if (*(args[arg+3])) {
6102 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006103 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006104 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006105 err_code |= ERR_ALERT | ERR_FATAL;
6106 goto out;
6107
Willy Tarreaubaaee002006-06-26 02:48:02 +02006108 }
6109 }
6110
William Lallemand0f99e342011-10-12 17:50:54 +02006111 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006112 if (*(args[arg+4])) {
6113 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006114 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006115 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006116 err_code |= ERR_ALERT | ERR_FATAL;
6117 goto out;
6118
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006119 }
6120 }
6121
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006122 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006123 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006124 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006125 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006126 goto out;
6127 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006128
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006129 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006130
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006131 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006132 if (port1 != port2) {
6133 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6134 file, linenum, args[0], args[1]);
6135 err_code |= ERR_ALERT | ERR_FATAL;
6136 goto out;
6137 }
6138
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006139 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006140 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006141 }
William Lallemand0f99e342011-10-12 17:50:54 +02006142
6143 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006144 }
6145 else {
6146 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6147 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006148 err_code |= ERR_ALERT | ERR_FATAL;
6149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006150 }
6151 }
6152 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006153 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006154 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006155 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006156 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006157
Willy Tarreau977b8e42006-12-29 14:19:17 +01006158 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006159 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006160
Willy Tarreaubaaee002006-06-26 02:48:02 +02006161 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006162 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6163 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006164 err_code |= ERR_ALERT | ERR_FATAL;
6165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006166 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006167
6168 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006169 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6170 free(curproxy->conn_src.iface_name);
6171 curproxy->conn_src.iface_name = NULL;
6172 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006173
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006174 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006175 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006176 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006177 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006178 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006179 goto out;
6180 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006181
6182 proto = protocol_by_family(sk->ss_family);
6183 if (!proto || !proto->connect) {
6184 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006185 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006186 err_code |= ERR_ALERT | ERR_FATAL;
6187 goto out;
6188 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006189
6190 if (port1 != port2) {
6191 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6192 file, linenum, args[0], args[1]);
6193 err_code |= ERR_ALERT | ERR_FATAL;
6194 goto out;
6195 }
6196
Willy Tarreauef9a3602012-12-08 22:29:20 +01006197 curproxy->conn_src.source_addr = *sk;
6198 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006199
6200 cur_arg = 2;
6201 while (*(args[cur_arg])) {
6202 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006203#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006204 if (!*args[cur_arg + 1]) {
6205 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6206 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006207 err_code |= ERR_ALERT | ERR_FATAL;
6208 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006209 }
6210
6211 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006212 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6213 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006214 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006215 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6216 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006217 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6218 char *name, *end;
6219
6220 name = args[cur_arg+1] + 7;
6221 while (isspace(*name))
6222 name++;
6223
6224 end = name;
6225 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6226 end++;
6227
Willy Tarreauef9a3602012-12-08 22:29:20 +01006228 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6229 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6230 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6231 curproxy->conn_src.bind_hdr_len = end - name;
6232 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6233 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6234 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006235
6236 /* now look for an occurrence number */
6237 while (isspace(*end))
6238 end++;
6239 if (*end == ',') {
6240 end++;
6241 name = end;
6242 if (*end == '-')
6243 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006244 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006245 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006246 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006247 }
6248
Willy Tarreauef9a3602012-12-08 22:29:20 +01006249 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006250 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6251 " occurrences values smaller than %d.\n",
6252 file, linenum, MAX_HDR_HISTORY);
6253 err_code |= ERR_ALERT | ERR_FATAL;
6254 goto out;
6255 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006256 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006257 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006258
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006259 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006260 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006261 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006262 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006263 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006264 goto out;
6265 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006266
6267 proto = protocol_by_family(sk->ss_family);
6268 if (!proto || !proto->connect) {
6269 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6270 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006271 err_code |= ERR_ALERT | ERR_FATAL;
6272 goto out;
6273 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006274
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006275 if (port1 != port2) {
6276 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6277 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006278 err_code |= ERR_ALERT | ERR_FATAL;
6279 goto out;
6280 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006281 curproxy->conn_src.tproxy_addr = *sk;
6282 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006283 }
6284 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006285#else /* no TPROXY support */
6286 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006287 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006288 err_code |= ERR_ALERT | ERR_FATAL;
6289 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006290#endif
6291 cur_arg += 2;
6292 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006293 }
6294
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006295 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6296#ifdef SO_BINDTODEVICE
6297 if (!*args[cur_arg + 1]) {
6298 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6299 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006300 err_code |= ERR_ALERT | ERR_FATAL;
6301 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006302 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006303 free(curproxy->conn_src.iface_name);
6304 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6305 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006306 global.last_checks |= LSTCHK_NETADM;
6307#else
6308 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6309 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006310 err_code |= ERR_ALERT | ERR_FATAL;
6311 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006312#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006313 cur_arg += 2;
6314 continue;
6315 }
6316 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006317 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006318 err_code |= ERR_ALERT | ERR_FATAL;
6319 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006320 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006321 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006322 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6323 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6324 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006325 err_code |= ERR_ALERT | ERR_FATAL;
6326 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006327 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006328 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006329 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006330 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6331 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006332 err_code |= ERR_ALERT | ERR_FATAL;
6333 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006334 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006335
6336 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006337 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006338 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006339 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006341 }
6342 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006343 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006344 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006345 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006346 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006348 }
6349 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006350 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006351 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006352 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006353 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006355 }
6356 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006357 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006358 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006359 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006360 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006362 }
6363 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006364 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006365 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006366 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006367 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006369 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006370 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006371 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006372 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006373 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006374 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006375 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006376 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006377 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006378 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006379 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6380 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006381 err_code |= ERR_ALERT | ERR_FATAL;
6382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006383 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006384
6385 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006386 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006387 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006388 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006390 }
6391 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006392 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006393 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006394 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006395 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006397 }
6398 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006399 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006400 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006401 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006402 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006404 }
6405 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006406 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006407 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006408 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006409 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006411 }
6412 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006413 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006414 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006415 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006416 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006418 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006419 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006420 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006421 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006422 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006423 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006424 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006426 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006427 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006428
Willy Tarreaubaaee002006-06-26 02:48:02 +02006429 if (curproxy == &defproxy) {
6430 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006431 err_code |= ERR_ALERT | ERR_FATAL;
6432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006433 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006434 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006435 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006436
Willy Tarreaubaaee002006-06-26 02:48:02 +02006437 if (*(args[1]) == 0) {
6438 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006439 err_code |= ERR_ALERT | ERR_FATAL;
6440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006441 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006442
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006443 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006444 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6445 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6446 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006447 err_code |= ERR_ALERT | ERR_FATAL;
6448 goto out;
6449 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006450 err_code |= warnif_cond_conflicts(cond,
6451 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6452 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006453 }
6454 else if (*args[2]) {
6455 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6456 file, linenum, args[0], args[2]);
6457 err_code |= ERR_ALERT | ERR_FATAL;
6458 goto out;
6459 }
6460
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006461 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006462 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006463 wl->s = strdup(args[1]);
6464 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006465 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006466 }
6467 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006468 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006469 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6470 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006471 err_code |= ERR_ALERT | ERR_FATAL;
6472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006473 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006474
Willy Tarreauade5ec42010-01-28 19:33:49 +01006475 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006476 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006477 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006478 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006479 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006480 }
6481 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006482 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006483 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006484 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006485 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006487 }
6488 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006489 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006490 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006491 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006492 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006494 }
6495 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006496 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006497 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6498 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006499 err_code |= ERR_ALERT | ERR_FATAL;
6500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006501 }
6502
Willy Tarreauade5ec42010-01-28 19:33:49 +01006503 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006504 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006505 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006506 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006507 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006508 }
6509 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006510 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006511 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006512 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006513 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006514 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006515 }
6516 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006517 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006518 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006519 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006520 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006522 }
6523 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006524 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006525
Willy Tarreaubaaee002006-06-26 02:48:02 +02006526 if (curproxy == &defproxy) {
6527 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006528 err_code |= ERR_ALERT | ERR_FATAL;
6529 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006530 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006531 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006532 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006533
Willy Tarreaubaaee002006-06-26 02:48:02 +02006534 if (*(args[1]) == 0) {
6535 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006536 err_code |= ERR_ALERT | ERR_FATAL;
6537 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006538 }
6539
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006540 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006541 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6542 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6543 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006544 err_code |= ERR_ALERT | ERR_FATAL;
6545 goto out;
6546 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006547 err_code |= warnif_cond_conflicts(cond,
6548 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6549 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006550 }
6551 else if (*args[2]) {
6552 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6553 file, linenum, args[0], args[2]);
6554 err_code |= ERR_ALERT | ERR_FATAL;
6555 goto out;
6556 }
6557
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006558 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006559 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006560 wl->s = strdup(args[1]);
6561 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006562 }
6563 else if (!strcmp(args[0], "errorloc") ||
6564 !strcmp(args[0], "errorloc302") ||
6565 !strcmp(args[0], "errorloc303")) { /* error location */
6566 int errnum, errlen;
6567 char *err;
6568
Willy Tarreau977b8e42006-12-29 14:19:17 +01006569 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006570 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006571
Willy Tarreaubaaee002006-06-26 02:48:02 +02006572 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006573 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006574 err_code |= ERR_ALERT | ERR_FATAL;
6575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006576 }
6577
6578 errnum = atol(args[1]);
6579 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006580 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6581 err = malloc(errlen);
6582 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006583 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006584 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6585 err = malloc(errlen);
6586 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006587 }
6588
Willy Tarreau0f772532006-12-23 20:51:41 +01006589 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6590 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006591 chunk_destroy(&curproxy->errmsg[rc]);
6592 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006593 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006594 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006595 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006596
6597 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006598 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6599 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006600 free(err);
6601 }
6602 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006603 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6604 int errnum, errlen, fd;
6605 char *err;
6606 struct stat stat;
6607
6608 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006609 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006610
6611 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006612 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006613 err_code |= ERR_ALERT | ERR_FATAL;
6614 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006615 }
6616
6617 fd = open(args[2], O_RDONLY);
6618 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6619 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6620 file, linenum, args[2], args[1]);
6621 if (fd >= 0)
6622 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006623 err_code |= ERR_ALERT | ERR_FATAL;
6624 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006625 }
6626
Willy Tarreau27a674e2009-08-17 07:23:33 +02006627 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006628 errlen = stat.st_size;
6629 } else {
6630 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006631 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006632 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006633 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006634 }
6635
6636 err = malloc(errlen); /* malloc() must succeed during parsing */
6637 errnum = read(fd, err, errlen);
6638 if (errnum != errlen) {
6639 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6640 file, linenum, args[2], args[1]);
6641 close(fd);
6642 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006643 err_code |= ERR_ALERT | ERR_FATAL;
6644 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006645 }
6646 close(fd);
6647
6648 errnum = atol(args[1]);
6649 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6650 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006651 chunk_destroy(&curproxy->errmsg[rc]);
6652 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006653 break;
6654 }
6655 }
6656
6657 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006658 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6659 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006660 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006661 free(err);
6662 }
6663 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006664 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006665 struct cfg_kw_list *kwl;
6666 int index;
6667
6668 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6669 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6670 if (kwl->kw[index].section != CFG_LISTEN)
6671 continue;
6672 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6673 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006674 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006675 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006676 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006677 err_code |= ERR_ALERT | ERR_FATAL;
6678 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006679 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006680 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006681 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006682 err_code |= ERR_WARN;
6683 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006684 }
Willy Tarreau93893792009-07-23 13:19:11 +02006685 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006686 }
6687 }
6688 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006689
Willy Tarreau6daf3432008-01-22 16:44:08 +01006690 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006691 err_code |= ERR_ALERT | ERR_FATAL;
6692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006693 }
Willy Tarreau93893792009-07-23 13:19:11 +02006694 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006695 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006696 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006697}
6698
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006699int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006700cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6701{
6702#ifdef CONFIG_HAP_NS
6703 const char *err;
6704 const char *item = args[0];
6705
6706 if (!strcmp(item, "namespace_list")) {
6707 return 0;
6708 }
6709 else if (!strcmp(item, "namespace")) {
6710 size_t idx = 1;
6711 const char *current;
6712 while (*(current = args[idx++])) {
6713 err = invalid_char(current);
6714 if (err) {
6715 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6716 file, linenum, *err, item, current);
6717 return ERR_ALERT | ERR_FATAL;
6718 }
6719
6720 if (netns_store_lookup(current, strlen(current))) {
6721 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6722 file, linenum, current);
6723 return ERR_ALERT | ERR_FATAL;
6724 }
6725 if (!netns_store_insert(current)) {
6726 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6727 file, linenum, current);
6728 return ERR_ALERT | ERR_FATAL;
6729 }
6730 }
6731 }
6732
6733 return 0;
6734#else
6735 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6736 file, linenum);
6737 return ERR_ALERT | ERR_FATAL;
6738#endif
6739}
6740
6741int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006742cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6743{
6744
6745 int err_code = 0;
6746 const char *err;
6747
6748 if (!strcmp(args[0], "userlist")) { /* new userlist */
6749 struct userlist *newul;
6750
6751 if (!*args[1]) {
6752 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6753 file, linenum, args[0]);
6754 err_code |= ERR_ALERT | ERR_FATAL;
6755 goto out;
6756 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006757 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6758 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006759
6760 err = invalid_char(args[1]);
6761 if (err) {
6762 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6763 file, linenum, *err, args[0], args[1]);
6764 err_code |= ERR_ALERT | ERR_FATAL;
6765 goto out;
6766 }
6767
6768 for (newul = userlist; newul; newul = newul->next)
6769 if (!strcmp(newul->name, args[1])) {
6770 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6771 file, linenum, args[1]);
6772 err_code |= ERR_WARN;
6773 goto out;
6774 }
6775
6776 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6777 if (!newul) {
6778 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6779 err_code |= ERR_ALERT | ERR_ABORT;
6780 goto out;
6781 }
6782
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006783 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006784 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006785 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6786 err_code |= ERR_ALERT | ERR_ABORT;
6787 goto out;
6788 }
6789
6790 newul->next = userlist;
6791 userlist = newul;
6792
6793 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006794 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006795 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006796 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006797
6798 if (!*args[1]) {
6799 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6800 file, linenum, args[0]);
6801 err_code |= ERR_ALERT | ERR_FATAL;
6802 goto out;
6803 }
6804
6805 err = invalid_char(args[1]);
6806 if (err) {
6807 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6808 file, linenum, *err, args[0], args[1]);
6809 err_code |= ERR_ALERT | ERR_FATAL;
6810 goto out;
6811 }
6812
William Lallemand4ac9f542015-05-28 18:03:51 +02006813 if (!userlist)
6814 goto out;
6815
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006816 for (ag = userlist->groups; ag; ag = ag->next)
6817 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006818 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6819 file, linenum, args[1], userlist->name);
6820 err_code |= ERR_ALERT;
6821 goto out;
6822 }
6823
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006824 ag = calloc(1, sizeof(*ag));
6825 if (!ag) {
6826 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6827 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006828 goto out;
6829 }
6830
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006831 ag->name = strdup(args[1]);
6832 if (!ag) {
6833 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6834 err_code |= ERR_ALERT | ERR_ABORT;
6835 goto out;
6836 }
6837
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006838 cur_arg = 2;
6839
6840 while (*args[cur_arg]) {
6841 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006842 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006843 cur_arg += 2;
6844 continue;
6845 } else {
6846 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6847 file, linenum, args[0]);
6848 err_code |= ERR_ALERT | ERR_FATAL;
6849 goto out;
6850 }
6851 }
6852
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006853 ag->next = userlist->groups;
6854 userlist->groups = ag;
6855
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006856 } else if (!strcmp(args[0], "user")) { /* new user */
6857 struct auth_users *newuser;
6858 int cur_arg;
6859
6860 if (!*args[1]) {
6861 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6862 file, linenum, args[0]);
6863 err_code |= ERR_ALERT | ERR_FATAL;
6864 goto out;
6865 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006866 if (!userlist)
6867 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006868
6869 for (newuser = userlist->users; newuser; newuser = newuser->next)
6870 if (!strcmp(newuser->user, args[1])) {
6871 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6872 file, linenum, args[1], userlist->name);
6873 err_code |= ERR_ALERT;
6874 goto out;
6875 }
6876
6877 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6878 if (!newuser) {
6879 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6880 err_code |= ERR_ALERT | ERR_ABORT;
6881 goto out;
6882 }
6883
6884 newuser->user = strdup(args[1]);
6885
6886 newuser->next = userlist->users;
6887 userlist->users = newuser;
6888
6889 cur_arg = 2;
6890
6891 while (*args[cur_arg]) {
6892 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006893#ifdef CONFIG_HAP_CRYPT
6894 if (!crypt("", args[cur_arg + 1])) {
6895 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6896 file, linenum, newuser->user);
6897 err_code |= ERR_ALERT | ERR_FATAL;
6898 goto out;
6899 }
6900#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006901 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6902 file, linenum);
6903 err_code |= ERR_ALERT;
6904#endif
6905 newuser->pass = strdup(args[cur_arg + 1]);
6906 cur_arg += 2;
6907 continue;
6908 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6909 newuser->pass = strdup(args[cur_arg + 1]);
6910 newuser->flags |= AU_O_INSECURE;
6911 cur_arg += 2;
6912 continue;
6913 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006914 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006915 cur_arg += 2;
6916 continue;
6917 } else {
6918 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6919 file, linenum, args[0]);
6920 err_code |= ERR_ALERT | ERR_FATAL;
6921 goto out;
6922 }
6923 }
6924 } else {
6925 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6926 err_code |= ERR_ALERT | ERR_FATAL;
6927 }
6928
6929out:
6930 return err_code;
6931}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006932
6933/*
6934 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006935 * Returns the error code, 0 if OK, or any combination of :
6936 * - ERR_ABORT: must abort ASAP
6937 * - ERR_FATAL: we can continue parsing but not start the service
6938 * - ERR_WARN: a warning has been emitted
6939 * - ERR_ALERT: an alert has been emitted
6940 * Only the two first ones can stop processing, the two others are just
6941 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006942 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006943int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006944{
William Lallemand64e84512015-05-12 14:25:37 +02006945 char *thisline;
6946 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006947 FILE *f;
6948 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006949 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006950 struct cfg_section *cs = NULL;
6951 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006952 int readbytes = 0;
6953
6954 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006955 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006956 return -1;
6957 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006958
6959 /* Register internal sections */
6960 if (!cfg_register_section("listen", cfg_parse_listen) ||
6961 !cfg_register_section("frontend", cfg_parse_listen) ||
6962 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006963 !cfg_register_section("defaults", cfg_parse_listen) ||
6964 !cfg_register_section("global", cfg_parse_global) ||
6965 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006966 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006967 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006968 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6969 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006970 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006971
Willy Tarreaubaaee002006-06-26 02:48:02 +02006972 if ((f=fopen(file,"r")) == NULL)
6973 return -1;
6974
William Lallemandb2f07452015-05-12 14:27:13 +02006975next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006976 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006977 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006978 char *end;
6979 char *args[MAX_LINE_ARGS + 1];
6980 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006981 int dquote = 0; /* double quote */
6982 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006983
Willy Tarreaubaaee002006-06-26 02:48:02 +02006984 linenum++;
6985
6986 end = line + strlen(line);
6987
William Lallemand64e84512015-05-12 14:25:37 +02006988 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006989 /* Check if we reached the limit and the last char is not \n.
6990 * Watch out for the last line without the terminating '\n'!
6991 */
William Lallemand64e84512015-05-12 14:25:37 +02006992 char *newline;
6993 int newlinesize = linesize * 2;
6994
6995 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6996 if (newline == NULL) {
6997 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6998 file, linenum);
6999 err_code |= ERR_ALERT | ERR_FATAL;
7000 continue;
7001 }
7002
7003 readbytes = linesize - 1;
7004 linesize = newlinesize;
7005 thisline = newline;
7006 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007007 }
7008
William Lallemand64e84512015-05-12 14:25:37 +02007009 readbytes = 0;
7010
Willy Tarreaubaaee002006-06-26 02:48:02 +02007011 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007012 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007013 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007014
Willy Tarreaubaaee002006-06-26 02:48:02 +02007015 arg = 0;
7016 args[arg] = line;
7017
7018 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007019 if (*line == '"' && !squote) { /* double quote outside single quotes */
7020 if (dquote)
7021 dquote = 0;
7022 else
7023 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007024 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007025 end--;
7026 }
7027 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7028 if (squote)
7029 squote = 0;
7030 else
7031 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007032 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007033 end--;
7034 }
7035 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007036 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7037 * C equivalent value. Other combinations left unchanged (eg: \1).
7038 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007039 int skip = 0;
7040 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7041 *line = line[1];
7042 skip = 1;
7043 }
7044 else if (line[1] == 'r') {
7045 *line = '\r';
7046 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007047 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007048 else if (line[1] == 'n') {
7049 *line = '\n';
7050 skip = 1;
7051 }
7052 else if (line[1] == 't') {
7053 *line = '\t';
7054 skip = 1;
7055 }
7056 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007057 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007058 unsigned char hex1, hex2;
7059 hex1 = toupper(line[2]) - '0';
7060 hex2 = toupper(line[3]) - '0';
7061 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7062 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7063 *line = (hex1<<4) + hex2;
7064 skip = 3;
7065 }
7066 else {
7067 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007068 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007069 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007070 } else if (line[1] == '"') {
7071 *line = '"';
7072 skip = 1;
7073 } else if (line[1] == '\'') {
7074 *line = '\'';
7075 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007076 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7077 *line = '$';
7078 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007079 }
7080 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007081 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007082 end -= skip;
7083 }
7084 line++;
7085 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007086 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007087 /* end of string, end of loop */
7088 *line = 0;
7089 break;
7090 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007091 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007092 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007093 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007094 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007095 line++;
7096 args[++arg] = line;
7097 }
William Lallemandb2f07452015-05-12 14:27:13 +02007098 else if (dquote && *line == '$') {
7099 /* environment variables are evaluated inside double quotes */
7100 char *var_beg;
7101 char *var_end;
7102 char save_char;
7103 char *value;
7104 int val_len;
7105 int newlinesize;
7106 int braces = 0;
7107
7108 var_beg = line + 1;
7109 var_end = var_beg;
7110
7111 if (*var_beg == '{') {
7112 var_beg++;
7113 var_end++;
7114 braces = 1;
7115 }
7116
7117 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7118 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7119 err_code |= ERR_ALERT | ERR_FATAL;
7120 goto next_line; /* skip current line */
7121 }
7122
7123 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7124 var_end++;
7125
7126 save_char = *var_end;
7127 *var_end = '\0';
7128 value = getenv(var_beg);
7129 *var_end = save_char;
7130 val_len = value ? strlen(value) : 0;
7131
7132 if (braces) {
7133 if (*var_end == '}') {
7134 var_end++;
7135 braces = 0;
7136 } else {
7137 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7138 err_code |= ERR_ALERT | ERR_FATAL;
7139 goto next_line; /* skip current line */
7140 }
7141 }
7142
7143 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7144
7145 /* if not enough space in thisline */
7146 if (newlinesize > linesize) {
7147 char *newline;
7148
7149 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7150 if (newline == NULL) {
7151 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7152 err_code |= ERR_ALERT | ERR_FATAL;
7153 goto next_line; /* slip current line */
7154 }
7155 /* recompute pointers if realloc returns a new pointer */
7156 if (newline != thisline) {
7157 int i;
7158 int diff;
7159
7160 for (i = 0; i <= arg; i++) {
7161 diff = args[i] - thisline;
7162 args[i] = newline + diff;
7163 }
7164
7165 diff = var_end - thisline;
7166 var_end = newline + diff;
7167 diff = end - thisline;
7168 end = newline + diff;
7169 diff = line - thisline;
7170 line = newline + diff;
7171 thisline = newline;
7172 }
7173 linesize = newlinesize;
7174 }
7175
7176 /* insert value inside the line */
7177 memmove(line + val_len, var_end, end - var_end + 1);
7178 memcpy(line, value, val_len);
7179 end += val_len - (var_end - line);
7180 line += val_len;
7181 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007182 else {
7183 line++;
7184 }
7185 }
William Lallemandb2f07452015-05-12 14:27:13 +02007186
William Lallemandf9873ba2015-05-05 17:37:14 +02007187 if (dquote) {
7188 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7189 err_code |= ERR_ALERT | ERR_FATAL;
7190 }
7191
7192 if (squote) {
7193 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7194 err_code |= ERR_ALERT | ERR_FATAL;
7195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007196
7197 /* empty line */
7198 if (!**args)
7199 continue;
7200
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007201 if (*line) {
7202 /* we had to stop due to too many args.
7203 * Let's terminate the string, print the offending part then cut the
7204 * last arg.
7205 */
7206 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7207 line++;
7208 *line = '\0';
7209
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007210 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007211 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007212 err_code |= ERR_ALERT | ERR_FATAL;
7213 args[arg] = line;
7214 }
7215
Willy Tarreau540abe42007-05-02 20:50:16 +02007216 /* zero out remaining args and ensure that at least one entry
7217 * is zeroed out.
7218 */
7219 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007220 args[arg] = line;
7221 }
7222
Willy Tarreau3842f002009-06-14 11:39:52 +02007223 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007224 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007225 char *tmp;
7226
Willy Tarreau3842f002009-06-14 11:39:52 +02007227 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007228 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007229 for (arg=0; *args[arg+1]; arg++)
7230 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007231 *tmp = '\0'; // fix the next arg to \0
7232 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007233 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007234 else if (!strcmp(args[0], "default")) {
7235 kwm = KWM_DEF;
7236 for (arg=0; *args[arg+1]; arg++)
7237 args[arg] = args[arg+1]; // shift args after inversion
7238 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007239
William Lallemand0f99e342011-10-12 17:50:54 +02007240 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7241 strcmp(args[0], "log") != 0) {
7242 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007243 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007244 }
7245
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007246 /* detect section start */
7247 list_for_each_entry(ics, &sections, list) {
7248 if (strcmp(args[0], ics->section_name) == 0) {
7249 cursection = ics->section_name;
7250 cs = ics;
7251 break;
7252 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007253 }
7254
Willy Tarreaubaaee002006-06-26 02:48:02 +02007255 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007256 if (cs)
7257 err_code |= cs->section_parser(file, linenum, args, kwm);
7258 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007259 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007260 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007261 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007262
7263 if (err_code & ERR_ABORT)
7264 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007265 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007266 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007267 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007268 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007269 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007270}
7271
Willy Tarreau64ab6072014-09-16 12:17:36 +02007272/* This function propagates processes from frontend <from> to backend <to> so
7273 * that it is always guaranteed that a backend pointed to by a frontend is
7274 * bound to all of its processes. After that, if the target is a "listen"
7275 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007276 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007277 * checked first to ensure that <to> is already bound to all processes of
7278 * <from>, there is no risk of looping and we ensure to follow the shortest
7279 * path to the destination.
7280 *
7281 * It is possible to set <to> to NULL for the first call so that the function
7282 * takes care of visiting the initial frontend in <from>.
7283 *
7284 * It is important to note that the function relies on the fact that all names
7285 * have already been resolved.
7286 */
7287void propagate_processes(struct proxy *from, struct proxy *to)
7288{
7289 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007290
7291 if (to) {
7292 /* check whether we need to go down */
7293 if (from->bind_proc &&
7294 (from->bind_proc & to->bind_proc) == from->bind_proc)
7295 return;
7296
7297 if (!from->bind_proc && !to->bind_proc)
7298 return;
7299
7300 to->bind_proc = from->bind_proc ?
7301 (to->bind_proc | from->bind_proc) : 0;
7302
7303 /* now propagate down */
7304 from = to;
7305 }
7306
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007307 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007308 return;
7309
Willy Tarreauf6b70012014-12-18 14:00:43 +01007310 if (from->state == PR_STSTOPPED)
7311 return;
7312
Willy Tarreau64ab6072014-09-16 12:17:36 +02007313 /* default_backend */
7314 if (from->defbe.be)
7315 propagate_processes(from, from->defbe.be);
7316
7317 /* use_backend */
7318 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007319 if (rule->dynamic)
7320 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007321 to = rule->be.backend;
7322 propagate_processes(from, to);
7323 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007324}
7325
Willy Tarreaubb925012009-07-23 13:36:36 +02007326/*
7327 * Returns the error code, 0 if OK, or any combination of :
7328 * - ERR_ABORT: must abort ASAP
7329 * - ERR_FATAL: we can continue parsing but not start the service
7330 * - ERR_WARN: a warning has been emitted
7331 * - ERR_ALERT: an alert has been emitted
7332 * Only the two first ones can stop processing, the two others are just
7333 * indicators.
7334 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007335int check_config_validity()
7336{
7337 int cfgerr = 0;
7338 struct proxy *curproxy = NULL;
7339 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007340 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007341 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007342 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007343
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007344 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007345 /*
7346 * Now, check for the integrity of all that we have collected.
7347 */
7348
7349 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007350 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007351
Willy Tarreau193b8c62012-11-22 00:17:38 +01007352 if (!global.tune.max_http_hdr)
7353 global.tune.max_http_hdr = MAX_HTTP_HDR;
7354
7355 if (!global.tune.cookie_len)
7356 global.tune.cookie_len = CAPTURE_LEN;
7357
7358 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7359
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007360 /* Post initialisation of the users and groups lists. */
7361 err_code = userlist_postinit();
7362 if (err_code != ERR_NONE)
7363 goto out;
7364
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007365 /* first, we will invert the proxy list order */
7366 curproxy = NULL;
7367 while (proxy) {
7368 struct proxy *next;
7369
7370 next = proxy->next;
7371 proxy->next = curproxy;
7372 curproxy = proxy;
7373 if (!next)
7374 break;
7375 proxy = next;
7376 }
7377
Willy Tarreau419ead82014-09-16 13:41:21 +02007378 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007379 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007380 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007381 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007382 struct act_rule *trule;
7383 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007384 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007385 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007386 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007387
Willy Tarreau050536d2012-10-04 08:47:34 +02007388 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007389 /* proxy ID not set, use automatic numbering with first
7390 * spare entry starting with next_pxid.
7391 */
7392 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7393 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7394 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007395 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007396 next_pxid++;
7397
Willy Tarreau55ea7572007-06-17 19:56:27 +02007398
Willy Tarreaubaaee002006-06-26 02:48:02 +02007399 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007400 /* ensure we don't keep listeners uselessly bound */
7401 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007402 free((void *)curproxy->table.peers.name);
7403 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007404 continue;
7405 }
7406
Willy Tarreau102df612014-05-07 23:56:38 +02007407 /* Check multi-process mode compatibility for the current proxy */
7408
7409 if (curproxy->bind_proc) {
7410 /* an explicit bind-process was specified, let's check how many
7411 * processes remain.
7412 */
David Carliere6c39412015-07-02 07:00:17 +00007413 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007414
7415 curproxy->bind_proc &= nbits(global.nbproc);
7416 if (!curproxy->bind_proc && nbproc == 1) {
7417 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);
7418 curproxy->bind_proc = 1;
7419 }
7420 else if (!curproxy->bind_proc && nbproc > 1) {
7421 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);
7422 curproxy->bind_proc = 0;
7423 }
7424 }
7425
Willy Tarreau3d209582014-05-09 17:06:11 +02007426 /* check and reduce the bind-proc of each listener */
7427 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7428 unsigned long mask;
7429
7430 if (!bind_conf->bind_proc)
7431 continue;
7432
7433 mask = nbits(global.nbproc);
7434 if (curproxy->bind_proc)
7435 mask &= curproxy->bind_proc;
7436 /* mask cannot be null here thanks to the previous checks */
7437
David Carliere6c39412015-07-02 07:00:17 +00007438 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007439 bind_conf->bind_proc &= mask;
7440
7441 if (!bind_conf->bind_proc && nbproc == 1) {
7442 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",
7443 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7444 bind_conf->bind_proc = mask & ~(mask - 1);
7445 }
7446 else if (!bind_conf->bind_proc && nbproc > 1) {
7447 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",
7448 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7449 bind_conf->bind_proc = 0;
7450 }
7451 }
7452
Willy Tarreauff01a212009-03-15 13:46:16 +01007453 switch (curproxy->mode) {
7454 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007455 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007456 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007457 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7458 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007459 cfgerr++;
7460 }
7461
7462 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007463 Warning("config : servers will be ignored for %s '%s'.\n",
7464 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007465 break;
7466
7467 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007468 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007469 break;
7470
7471 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007472 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007473 break;
7474 }
7475
Willy Tarreauf3934b82015-08-11 11:36:45 +02007476 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7477 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7478 proxy_type_str(curproxy), curproxy->id);
7479 err_code |= ERR_WARN;
7480 }
7481
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007482 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007483 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007484 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007485 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7486 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007487 cfgerr++;
7488 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007489#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007490 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007491 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7492 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007493 cfgerr++;
7494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007495#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007496 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007497 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7498 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007499 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007500 }
7501 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007502 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007503 /* If no LB algo is set in a backend, and we're not in
7504 * transparent mode, dispatch mode nor proxy mode, we
7505 * want to use balance roundrobin by default.
7506 */
7507 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7508 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007509 }
7510 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007511
Willy Tarreau1620ec32011-08-06 17:05:02 +02007512 if (curproxy->options & PR_O_DISPATCH)
7513 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7514 else if (curproxy->options & PR_O_HTTP_PROXY)
7515 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7516 else if (curproxy->options & PR_O_TRANSP)
7517 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007518
Willy Tarreau1620ec32011-08-06 17:05:02 +02007519 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7520 if (curproxy->options & PR_O_DISABLE404) {
7521 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7522 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7523 err_code |= ERR_WARN;
7524 curproxy->options &= ~PR_O_DISABLE404;
7525 }
7526 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7527 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7528 "send-state", proxy_type_str(curproxy), curproxy->id);
7529 err_code |= ERR_WARN;
7530 curproxy->options &= ~PR_O2_CHK_SNDST;
7531 }
Willy Tarreauef781042010-01-27 11:53:01 +01007532 }
7533
Simon Horman98637e52014-06-20 12:30:16 +09007534 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7535 if (!global.external_check) {
7536 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7537 curproxy->id, "option external-check");
7538 cfgerr++;
7539 }
7540 if (!curproxy->check_command) {
7541 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7542 curproxy->id, "option external-check");
7543 cfgerr++;
7544 }
7545 }
7546
Simon Horman64e34162015-02-06 11:11:57 +09007547 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007548 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7549 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007550 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7551 "'email-alert myhostname', or 'email-alert to' "
7552 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007553 "to be present).\n",
7554 proxy_type_str(curproxy), curproxy->id);
7555 err_code |= ERR_WARN;
7556 free_email_alert(curproxy);
7557 }
7558 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007559 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007560 }
7561
Simon Horman98637e52014-06-20 12:30:16 +09007562 if (curproxy->check_command) {
7563 int clear = 0;
7564 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7565 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7566 "external-check command", proxy_type_str(curproxy), curproxy->id);
7567 err_code |= ERR_WARN;
7568 clear = 1;
7569 }
7570 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007571 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007572 curproxy->id, "external-check command");
7573 cfgerr++;
7574 }
7575 if (clear) {
7576 free(curproxy->check_command);
7577 curproxy->check_command = NULL;
7578 }
7579 }
7580
7581 if (curproxy->check_path) {
7582 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7583 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7584 "external-check path", proxy_type_str(curproxy), curproxy->id);
7585 err_code |= ERR_WARN;
7586 free(curproxy->check_path);
7587 curproxy->check_path = NULL;
7588 }
7589 }
7590
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007591 /* if a default backend was specified, let's find it */
7592 if (curproxy->defbe.name) {
7593 struct proxy *target;
7594
Willy Tarreauafb39922015-05-26 12:04:09 +02007595 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007596 if (!target) {
7597 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7598 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007599 cfgerr++;
7600 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007601 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7602 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007603 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007604 } else if (target->mode != curproxy->mode &&
7605 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7606
7607 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7608 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7609 curproxy->conf.file, curproxy->conf.line,
7610 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7611 target->conf.file, target->conf.line);
7612 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007613 } else {
7614 free(curproxy->defbe.name);
7615 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007616
7617 /* Emit a warning if this proxy also has some servers */
7618 if (curproxy->srv) {
7619 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7620 curproxy->id);
7621 err_code |= ERR_WARN;
7622 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007623 }
7624 }
7625
Willy Tarreau55ea7572007-06-17 19:56:27 +02007626 /* find the target proxy for 'use_backend' rules */
7627 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007628 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007629 struct logformat_node *node;
7630 char *pxname;
7631
7632 /* Try to parse the string as a log format expression. If the result
7633 * of the parsing is only one entry containing a simple string, then
7634 * it's a standard string corresponding to a static rule, thus the
7635 * parsing is cancelled and be.name is restored to be resolved.
7636 */
7637 pxname = rule->be.name;
7638 LIST_INIT(&rule->be.expr);
7639 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7640 curproxy->conf.args.file, curproxy->conf.args.line);
7641 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7642
7643 if (!LIST_ISEMPTY(&rule->be.expr)) {
7644 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7645 rule->dynamic = 1;
7646 free(pxname);
7647 continue;
7648 }
7649 /* simple string: free the expression and fall back to static rule */
7650 free(node->arg);
7651 free(node);
7652 }
7653
7654 rule->dynamic = 0;
7655 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007656
Willy Tarreauafb39922015-05-26 12:04:09 +02007657 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007658 if (!target) {
7659 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7660 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007661 cfgerr++;
7662 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007663 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7664 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007665 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007666 } else if (target->mode != curproxy->mode &&
7667 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7668
7669 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7670 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7671 curproxy->conf.file, curproxy->conf.line,
7672 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7673 target->conf.file, target->conf.line);
7674 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007675 } else {
7676 free((void *)rule->be.name);
7677 rule->be.backend = target;
7678 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007679 }
7680
Willy Tarreau64ab6072014-09-16 12:17:36 +02007681 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007682 list_for_each_entry(srule, &curproxy->server_rules, list) {
7683 struct server *target = findserver(curproxy, srule->srv.name);
7684
7685 if (!target) {
7686 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7687 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7688 cfgerr++;
7689 continue;
7690 }
7691 free((void *)srule->srv.name);
7692 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007693 }
7694
Emeric Brunb982a3d2010-01-04 15:45:53 +01007695 /* find the target table for 'stick' rules */
7696 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7697 struct proxy *target;
7698
Emeric Brun1d33b292010-01-04 15:47:17 +01007699 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7700 if (mrule->flags & STK_IS_STORE)
7701 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7702
Emeric Brunb982a3d2010-01-04 15:45:53 +01007703 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007704 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007705 else
7706 target = curproxy;
7707
7708 if (!target) {
7709 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7710 curproxy->id, mrule->table.name);
7711 cfgerr++;
7712 }
7713 else if (target->table.size == 0) {
7714 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7715 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7716 cfgerr++;
7717 }
Willy Tarreau12785782012-04-27 21:37:17 +02007718 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7719 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007720 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7721 cfgerr++;
7722 }
7723 else {
7724 free((void *)mrule->table.name);
7725 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007726 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007727 }
7728 }
7729
7730 /* find the target table for 'store response' rules */
7731 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7732 struct proxy *target;
7733
Emeric Brun1d33b292010-01-04 15:47:17 +01007734 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7735
Emeric Brunb982a3d2010-01-04 15:45:53 +01007736 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007737 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007738 else
7739 target = curproxy;
7740
7741 if (!target) {
7742 Alert("Proxy '%s': unable to find store table '%s'.\n",
7743 curproxy->id, mrule->table.name);
7744 cfgerr++;
7745 }
7746 else if (target->table.size == 0) {
7747 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7748 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7749 cfgerr++;
7750 }
Willy Tarreau12785782012-04-27 21:37:17 +02007751 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7752 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007753 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7754 cfgerr++;
7755 }
7756 else {
7757 free((void *)mrule->table.name);
7758 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007759 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007760 }
7761 }
7762
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007763 /* find the target table for 'tcp-request' layer 4 rules */
7764 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7765 struct proxy *target;
7766
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007767 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007768 continue;
7769
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007770 if (trule->arg.trk_ctr.table.n)
7771 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007772 else
7773 target = curproxy;
7774
7775 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007776 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007777 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007778 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007779 cfgerr++;
7780 }
7781 else if (target->table.size == 0) {
7782 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007783 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007784 cfgerr++;
7785 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007786 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007787 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007788 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007789 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007790 cfgerr++;
7791 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007792 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007793 free(trule->arg.trk_ctr.table.n);
7794 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007795 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007796 * to pass a list of counters to track and allocate them right here using
7797 * stktable_alloc_data_type().
7798 */
7799 }
7800 }
7801
Willy Tarreaud1f96522010-08-03 19:34:32 +02007802 /* find the target table for 'tcp-request' layer 6 rules */
7803 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7804 struct proxy *target;
7805
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007806 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007807 continue;
7808
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007809 if (trule->arg.trk_ctr.table.n)
7810 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007811 else
7812 target = curproxy;
7813
7814 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007815 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007816 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007817 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007818 cfgerr++;
7819 }
7820 else if (target->table.size == 0) {
7821 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007822 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007823 cfgerr++;
7824 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007825 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007826 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007827 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007828 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007829 cfgerr++;
7830 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007831 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007832 free(trule->arg.trk_ctr.table.n);
7833 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007834 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007835 * to pass a list of counters to track and allocate them right here using
7836 * stktable_alloc_data_type().
7837 */
7838 }
7839 }
7840
Baptiste Assmanne9544932015-11-03 23:31:35 +01007841 /* parse http-request capture rules to ensure id really exists */
7842 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7843 if (hrqrule->action != ACT_CUSTOM ||
7844 hrqrule->action_ptr != http_action_req_capture_by_id)
7845 continue;
7846
7847 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7848 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7849 curproxy->id, hrqrule->arg.capid.idx);
7850 cfgerr++;
7851 }
7852 }
7853
7854 /* parse http-response capture rules to ensure id really exists */
7855 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7856 if (hrqrule->action != ACT_CUSTOM ||
7857 hrqrule->action_ptr != http_action_res_capture_by_id)
7858 continue;
7859
7860 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7861 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7862 curproxy->id, hrqrule->arg.capid.idx);
7863 cfgerr++;
7864 }
7865 }
7866
Willy Tarreau09448f72014-06-25 18:12:15 +02007867 /* find the target table for 'http-request' layer 7 rules */
7868 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7869 struct proxy *target;
7870
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007871 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007872 continue;
7873
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007874 if (hrqrule->arg.trk_ctr.table.n)
7875 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007876 else
7877 target = curproxy;
7878
7879 if (!target) {
7880 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007881 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007882 http_req_trk_idx(hrqrule->action));
7883 cfgerr++;
7884 }
7885 else if (target->table.size == 0) {
7886 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007887 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007888 cfgerr++;
7889 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007890 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007891 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007892 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007893 http_req_trk_idx(hrqrule->action));
7894 cfgerr++;
7895 }
7896 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007897 free(hrqrule->arg.trk_ctr.table.n);
7898 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007899 /* Note: if we decide to enhance the track-sc syntax, we may be able
7900 * to pass a list of counters to track and allocate them right here using
7901 * stktable_alloc_data_type().
7902 */
7903 }
7904 }
7905
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007906 /* move any "block" rules at the beginning of the http-request rules */
7907 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7908 /* insert block_rules into http_req_rules at the beginning */
7909 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7910 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7911 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7912 curproxy->http_req_rules.n = curproxy->block_rules.n;
7913 LIST_INIT(&curproxy->block_rules);
7914 }
7915
Emeric Brun32da3c42010-09-23 18:39:19 +02007916 if (curproxy->table.peers.name) {
7917 struct peers *curpeers = peers;
7918
7919 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7920 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7921 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007922 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007923 break;
7924 }
7925 }
7926
7927 if (!curpeers) {
7928 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7929 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007930 free((void *)curproxy->table.peers.name);
7931 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007932 cfgerr++;
7933 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007934 else if (curpeers->state == PR_STSTOPPED) {
7935 /* silently disable this peers section */
7936 curproxy->table.peers.p = NULL;
7937 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007938 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007939 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7940 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007941 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007942 cfgerr++;
7943 }
7944 }
7945
Simon Horman9dc49962015-01-30 11:22:59 +09007946
7947 if (curproxy->email_alert.mailers.name) {
7948 struct mailers *curmailers = mailers;
7949
7950 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7951 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7952 free(curproxy->email_alert.mailers.name);
7953 curproxy->email_alert.mailers.m = curmailers;
7954 curmailers->users++;
7955 break;
7956 }
7957 }
7958
7959 if (!curmailers) {
7960 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7961 curproxy->id, curproxy->email_alert.mailers.name);
7962 free_email_alert(curproxy);
7963 cfgerr++;
7964 }
7965 }
7966
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007967 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007968 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007969 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7970 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7971 "proxy", curproxy->id);
7972 cfgerr++;
7973 goto out_uri_auth_compat;
7974 }
7975
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007976 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007977 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007978 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007979 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007980
Willy Tarreau95fa4692010-02-01 13:05:50 +01007981 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7982 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007983
7984 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007985 uri_auth_compat_req[i++] = "realm";
7986 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7987 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007988
Willy Tarreau95fa4692010-02-01 13:05:50 +01007989 uri_auth_compat_req[i++] = "unless";
7990 uri_auth_compat_req[i++] = "{";
7991 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7992 uri_auth_compat_req[i++] = "}";
7993 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007994
Willy Tarreauff011f22011-01-06 17:51:27 +01007995 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7996 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007997 cfgerr++;
7998 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007999 }
8000
Willy Tarreauff011f22011-01-06 17:51:27 +01008001 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008002
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008003 if (curproxy->uri_auth->auth_realm) {
8004 free(curproxy->uri_auth->auth_realm);
8005 curproxy->uri_auth->auth_realm = NULL;
8006 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008007
8008 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008009 }
8010out_uri_auth_compat:
8011
Dragan Dosen43885c72015-10-01 13:18:13 +02008012 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008013 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008014 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8015 if (!curproxy->conf.logformat_sd_string) {
8016 /* set the default logformat_sd_string */
8017 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8018 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008019 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008020 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008021 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008022
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008023 /* compile the log format */
8024 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008025 if (curproxy->conf.logformat_string != default_http_log_format &&
8026 curproxy->conf.logformat_string != default_tcp_log_format &&
8027 curproxy->conf.logformat_string != clf_http_log_format)
8028 free(curproxy->conf.logformat_string);
8029 curproxy->conf.logformat_string = NULL;
8030 free(curproxy->conf.lfs_file);
8031 curproxy->conf.lfs_file = NULL;
8032 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008033
8034 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8035 free(curproxy->conf.logformat_sd_string);
8036 curproxy->conf.logformat_sd_string = NULL;
8037 free(curproxy->conf.lfsd_file);
8038 curproxy->conf.lfsd_file = NULL;
8039 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008040 }
8041
Willy Tarreau62a61232013-04-12 18:13:46 +02008042 if (curproxy->conf.logformat_string) {
8043 curproxy->conf.args.ctx = ARGC_LOG;
8044 curproxy->conf.args.file = curproxy->conf.lfs_file;
8045 curproxy->conf.args.line = curproxy->conf.lfs_line;
8046 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008047 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008048 curproxy->conf.args.file = NULL;
8049 curproxy->conf.args.line = 0;
8050 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008051
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008052 if (curproxy->conf.logformat_sd_string) {
8053 curproxy->conf.args.ctx = ARGC_LOGSD;
8054 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8055 curproxy->conf.args.line = curproxy->conf.lfsd_line;
8056 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
8057 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
8058 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
8059 curproxy->conf.args.file = NULL;
8060 curproxy->conf.args.line = 0;
8061 }
8062
Willy Tarreau62a61232013-04-12 18:13:46 +02008063 if (curproxy->conf.uniqueid_format_string) {
8064 curproxy->conf.args.ctx = ARGC_UIF;
8065 curproxy->conf.args.file = curproxy->conf.uif_file;
8066 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01008067 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08008068 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008069 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008070 curproxy->conf.args.file = NULL;
8071 curproxy->conf.args.line = 0;
8072 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008073
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008074 /* only now we can check if some args remain unresolved.
8075 * This must be done after the users and groups resolution.
8076 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008077 cfgerr += smp_resolve_args(curproxy);
8078 if (!cfgerr)
8079 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008080
Willy Tarreau2738a142006-07-08 17:28:09 +02008081 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008082 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008083 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008084 (!curproxy->timeout.connect ||
8085 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008086 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008087 " | While not properly invalid, you will certainly encounter various problems\n"
8088 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008089 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008090 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008091 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008092 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008093
Willy Tarreau1fa31262007-12-03 00:36:16 +01008094 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8095 * We must still support older configurations, so let's find out whether those
8096 * parameters have been set or must be copied from contimeouts.
8097 */
8098 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008099 if (!curproxy->timeout.tarpit ||
8100 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008101 /* tarpit timeout not set. We search in the following order:
8102 * default.tarpit, curr.connect, default.connect.
8103 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008104 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008105 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008106 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008107 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008108 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008109 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008110 }
8111 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008112 (!curproxy->timeout.queue ||
8113 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008114 /* queue timeout not set. We search in the following order:
8115 * default.queue, curr.connect, default.connect.
8116 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008117 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008118 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008119 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008120 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008121 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008122 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008123 }
8124 }
8125
Willy Tarreau1620ec32011-08-06 17:05:02 +02008126 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008127 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
8128 curproxy->check_req = (char *)malloc(curproxy->check_len);
8129 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008130 }
8131
Willy Tarreau215663d2014-06-13 18:30:23 +02008132 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8133 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8134 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8135 proxy_type_str(curproxy), curproxy->id);
8136 err_code |= ERR_WARN;
8137 }
8138
Willy Tarreau193b8c62012-11-22 00:17:38 +01008139 /* ensure that cookie capture length is not too large */
8140 if (curproxy->capture_len >= global.tune.cookie_len) {
8141 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8142 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8143 err_code |= ERR_WARN;
8144 curproxy->capture_len = global.tune.cookie_len - 1;
8145 }
8146
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008147 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008148 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008149 curproxy->req_cap_pool = create_pool("ptrcap",
8150 curproxy->nb_req_cap * sizeof(char *),
8151 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008152 }
8153
8154 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008155 curproxy->rsp_cap_pool = create_pool("ptrcap",
8156 curproxy->nb_rsp_cap * sizeof(char *),
8157 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008158 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008159
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008160 switch (curproxy->load_server_state_from_file) {
8161 case PR_SRV_STATE_FILE_UNSPEC:
8162 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8163 break;
8164 case PR_SRV_STATE_FILE_GLOBAL:
8165 if (!global.server_state_file) {
8166 Warning("config : backend '%s' configured to load server state file from global section 'server-state-file' directive. Unfortunately, 'server-state-file' is not set!\n",
8167 curproxy->id);
8168 err_code |= ERR_WARN;
8169 }
8170 break;
8171 }
8172
Willy Tarreaubaaee002006-06-26 02:48:02 +02008173 /* first, we will invert the servers list order */
8174 newsrv = NULL;
8175 while (curproxy->srv) {
8176 struct server *next;
8177
8178 next = curproxy->srv->next;
8179 curproxy->srv->next = newsrv;
8180 newsrv = curproxy->srv;
8181 if (!next)
8182 break;
8183 curproxy->srv = next;
8184 }
8185
Willy Tarreau17edc812014-01-03 12:14:34 +01008186 /* Check that no server name conflicts. This causes trouble in the stats.
8187 * We only emit a warning for the first conflict affecting each server,
8188 * in order to avoid combinatory explosion if all servers have the same
8189 * name. We do that only for servers which do not have an explicit ID,
8190 * because these IDs were made also for distinguishing them and we don't
8191 * want to annoy people who correctly manage them.
8192 */
8193 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8194 struct server *other_srv;
8195
8196 if (newsrv->puid)
8197 continue;
8198
8199 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8200 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8201 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8202 newsrv->conf.file, newsrv->conf.line,
8203 proxy_type_str(curproxy), curproxy->id,
8204 newsrv->id, other_srv->conf.line);
8205 break;
8206 }
8207 }
8208 }
8209
Willy Tarreaudd701652010-05-25 23:03:02 +02008210 /* assign automatic UIDs to servers which don't have one yet */
8211 next_id = 1;
8212 newsrv = curproxy->srv;
8213 while (newsrv != NULL) {
8214 if (!newsrv->puid) {
8215 /* server ID not set, use automatic numbering with first
8216 * spare entry starting with next_svid.
8217 */
8218 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8219 newsrv->conf.id.key = newsrv->puid = next_id;
8220 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8221 }
8222 next_id++;
8223 newsrv = newsrv->next;
8224 }
8225
Willy Tarreau20697042007-11-15 23:26:18 +01008226 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008227 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008228
Willy Tarreau62c3be22012-01-20 13:12:32 +01008229 /*
8230 * If this server supports a maxconn parameter, it needs a dedicated
8231 * tasks to fill the emptied slots when a connection leaves.
8232 * Also, resolve deferred tracking dependency if needed.
8233 */
8234 newsrv = curproxy->srv;
8235 while (newsrv != NULL) {
8236 if (newsrv->minconn > newsrv->maxconn) {
8237 /* Only 'minconn' was specified, or it was higher than or equal
8238 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8239 * this will avoid further useless expensive computations.
8240 */
8241 newsrv->maxconn = newsrv->minconn;
8242 } else if (newsrv->maxconn && !newsrv->minconn) {
8243 /* minconn was not specified, so we set it to maxconn */
8244 newsrv->minconn = newsrv->maxconn;
8245 }
8246
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008247#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008248 if (newsrv->use_ssl || newsrv->check.use_ssl)
8249 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008250#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008251
Willy Tarreau2f075e92013-12-03 11:11:34 +01008252 /* set the check type on the server */
8253 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8254
Willy Tarreau62c3be22012-01-20 13:12:32 +01008255 if (newsrv->trackit) {
8256 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008257 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008258 char *pname, *sname;
8259
8260 pname = newsrv->trackit;
8261 sname = strrchr(pname, '/');
8262
8263 if (sname)
8264 *sname++ = '\0';
8265 else {
8266 sname = pname;
8267 pname = NULL;
8268 }
8269
8270 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008271 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008272 if (!px) {
8273 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8274 proxy_type_str(curproxy), curproxy->id,
8275 newsrv->id, pname);
8276 cfgerr++;
8277 goto next_srv;
8278 }
8279 } else
8280 px = curproxy;
8281
8282 srv = findserver(px, sname);
8283 if (!srv) {
8284 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8285 proxy_type_str(curproxy), curproxy->id,
8286 newsrv->id, sname);
8287 cfgerr++;
8288 goto next_srv;
8289 }
8290
Willy Tarreau32091232014-05-16 13:52:00 +02008291 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8292 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8293 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008294 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008295 "tracking as it does not have any check nor agent enabled.\n",
8296 proxy_type_str(curproxy), curproxy->id,
8297 newsrv->id, px->id, srv->id);
8298 cfgerr++;
8299 goto next_srv;
8300 }
8301
8302 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8303
8304 if (loop) {
8305 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8306 "belongs to a tracking chain looping back to %s/%s.\n",
8307 proxy_type_str(curproxy), curproxy->id,
8308 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008309 cfgerr++;
8310 goto next_srv;
8311 }
8312
8313 if (curproxy != px &&
8314 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8315 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8316 "tracking: disable-on-404 option inconsistency.\n",
8317 proxy_type_str(curproxy), curproxy->id,
8318 newsrv->id, px->id, srv->id);
8319 cfgerr++;
8320 goto next_srv;
8321 }
8322
8323 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008324 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008325 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008326 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008327 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008328 }
8329
8330 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008331 newsrv->tracknext = srv->trackers;
8332 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008333
8334 free(newsrv->trackit);
8335 newsrv->trackit = NULL;
8336 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008337
8338 /*
8339 * resolve server's resolvers name and update the resolvers pointer
8340 * accordingly
8341 */
8342 if (newsrv->resolvers_id) {
8343 struct dns_resolvers *curr_resolvers;
8344 int found;
8345
8346 found = 0;
8347 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8348 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8349 found = 1;
8350 break;
8351 }
8352 }
8353
8354 if (!found) {
8355 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8356 proxy_type_str(curproxy), curproxy->id,
8357 newsrv->id, newsrv->resolvers_id);
8358 cfgerr++;
8359 } else {
8360 free(newsrv->resolvers_id);
8361 newsrv->resolvers_id = NULL;
8362 if (newsrv->resolution)
8363 newsrv->resolution->resolvers = curr_resolvers;
8364 }
8365 }
8366 else {
8367 /* if no resolvers section associated to this server
8368 * we can clean up the associated resolution structure
8369 */
8370 if (newsrv->resolution) {
8371 free(newsrv->resolution->hostname_dn);
8372 newsrv->resolution->hostname_dn = NULL;
8373 free(newsrv->resolution);
8374 newsrv->resolution = NULL;
8375 }
8376 }
8377
Willy Tarreau62c3be22012-01-20 13:12:32 +01008378 next_srv:
8379 newsrv = newsrv->next;
8380 }
8381
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008382 /* We have to initialize the server lookup mechanism depending
8383 * on what LB algorithm was choosen.
8384 */
8385
8386 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8387 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8388 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008389 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8390 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8391 init_server_map(curproxy);
8392 } else {
8393 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8394 fwrr_init_server_groups(curproxy);
8395 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008396 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008397
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008398 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008399 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8400 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8401 fwlc_init_server_tree(curproxy);
8402 } else {
8403 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8404 fas_init_server_tree(curproxy);
8405 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008406 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008407
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008408 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008409 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8410 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8411 chash_init_server_tree(curproxy);
8412 } else {
8413 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8414 init_server_map(curproxy);
8415 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008416 break;
8417 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008418
8419 if (curproxy->options & PR_O_LOGASAP)
8420 curproxy->to_log &= ~LW_BYTES;
8421
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008422 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008423 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8424 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008425 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8426 proxy_type_str(curproxy), curproxy->id);
8427 err_code |= ERR_WARN;
8428 }
8429
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008430 if (curproxy->mode != PR_MODE_HTTP) {
8431 int optnum;
8432
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008433 if (curproxy->uri_auth) {
8434 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8435 proxy_type_str(curproxy), curproxy->id);
8436 err_code |= ERR_WARN;
8437 curproxy->uri_auth = NULL;
8438 }
8439
Willy Tarreau87cf5142011-08-19 22:57:24 +02008440 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008441 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8442 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8443 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008444 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008445 }
8446
8447 if (curproxy->options & PR_O_ORGTO) {
8448 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8449 "originalto", proxy_type_str(curproxy), curproxy->id);
8450 err_code |= ERR_WARN;
8451 curproxy->options &= ~PR_O_ORGTO;
8452 }
8453
8454 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8455 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8456 (curproxy->cap & cfg_opts[optnum].cap) &&
8457 (curproxy->options & cfg_opts[optnum].val)) {
8458 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8459 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8460 err_code |= ERR_WARN;
8461 curproxy->options &= ~cfg_opts[optnum].val;
8462 }
8463 }
8464
8465 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8466 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8467 (curproxy->cap & cfg_opts2[optnum].cap) &&
8468 (curproxy->options2 & cfg_opts2[optnum].val)) {
8469 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8470 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8471 err_code |= ERR_WARN;
8472 curproxy->options2 &= ~cfg_opts2[optnum].val;
8473 }
8474 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008475
Willy Tarreau29fbe512015-08-20 19:35:14 +02008476#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008477 if (curproxy->conn_src.bind_hdr_occ) {
8478 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008479 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008480 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008481 err_code |= ERR_WARN;
8482 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008483#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008484 }
8485
Willy Tarreaubaaee002006-06-26 02:48:02 +02008486 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008487 * ensure that we're not cross-dressing a TCP server into HTTP.
8488 */
8489 newsrv = curproxy->srv;
8490 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008491 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008492 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8493 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008494 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008495 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008496
Willy Tarreau0cec3312011-10-31 13:49:26 +01008497 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8498 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8499 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8500 err_code |= ERR_WARN;
8501 }
8502
Willy Tarreauc93cd162014-05-13 15:54:22 +02008503 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008504 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8505 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8506 err_code |= ERR_WARN;
8507 }
8508
Willy Tarreau29fbe512015-08-20 19:35:14 +02008509#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008510 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8511 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008512 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 +01008513 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008514 err_code |= ERR_WARN;
8515 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008516#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008517 newsrv = newsrv->next;
8518 }
8519
Willy Tarreaue42bd962014-09-16 16:21:19 +02008520 /* check if we have a frontend with "tcp-request content" looking at L7
8521 * with no inspect-delay
8522 */
8523 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8524 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008525 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008526 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008527 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008528 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008529 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008530 break;
8531 }
8532
8533 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8534 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8535 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8536 " This means that these rules will randomly find their contents. This can be fixed by"
8537 " setting the tcp-request inspect-delay.\n",
8538 proxy_type_str(curproxy), curproxy->id);
8539 err_code |= ERR_WARN;
8540 }
8541 }
8542
Christopher Fauletd7c91962015-04-30 11:48:27 +02008543 /* Check filter configuration, if any */
8544 cfgerr += flt_check(curproxy);
8545
Willy Tarreauc1a21672009-08-16 22:37:44 +02008546 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008547 if (!curproxy->accept)
8548 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008549
Willy Tarreauc1a21672009-08-16 22:37:44 +02008550 if (curproxy->tcp_req.inspect_delay ||
8551 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008552 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008553
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008554 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008555 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008556 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008557 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008558
8559 /* both TCP and HTTP must check switching rules */
8560 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008561
8562 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008563 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008564 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8565 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008566 if (curproxy->mode == PR_MODE_HTTP) {
8567 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8568 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8569 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008570 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008571 }
8572
8573 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008574 if (curproxy->tcp_req.inspect_delay ||
8575 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8576 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8577
Emeric Brun97679e72010-09-23 17:56:44 +02008578 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8579 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8580
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008581 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008582 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008583 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008584 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008585
8586 /* If the backend does requires RDP cookie persistence, we have to
8587 * enable the corresponding analyser.
8588 */
8589 if (curproxy->options2 & PR_O2_RDPC_PRST)
8590 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008591
8592 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008593 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008594 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8595 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008596 if (curproxy->mode == PR_MODE_HTTP) {
8597 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8598 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8599 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008600 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008601 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008602 }
8603
8604 /***********************************************************/
8605 /* At this point, target names have already been resolved. */
8606 /***********************************************************/
8607
8608 /* Check multi-process mode compatibility */
8609
8610 if (global.nbproc > 1 && global.stats_fe) {
8611 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8612 unsigned long mask;
8613
8614 mask = nbits(global.nbproc);
8615 if (global.stats_fe->bind_proc)
8616 mask &= global.stats_fe->bind_proc;
8617
8618 if (bind_conf->bind_proc)
8619 mask &= bind_conf->bind_proc;
8620
8621 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008622 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008623 break;
8624 }
8625 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8626 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");
8627 }
8628 }
8629
8630 /* Make each frontend inherit bind-process from its listeners when not specified. */
8631 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8632 if (curproxy->bind_proc)
8633 continue;
8634
8635 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8636 unsigned long mask;
8637
Willy Tarreaue428b082015-05-04 21:57:58 +02008638 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008639 curproxy->bind_proc |= mask;
8640 }
8641
8642 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008643 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008644 }
8645
8646 if (global.stats_fe) {
8647 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8648 unsigned long mask;
8649
Cyril Bonté06181952016-02-24 00:14:54 +01008650 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008651 global.stats_fe->bind_proc |= mask;
8652 }
8653 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008654 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008655 }
8656
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008657 /* propagate bindings from frontends to backends. Don't do it if there
8658 * are any fatal errors as we must not call it with unresolved proxies.
8659 */
8660 if (!cfgerr) {
8661 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8662 if (curproxy->cap & PR_CAP_FE)
8663 propagate_processes(curproxy, NULL);
8664 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008665 }
8666
8667 /* Bind each unbound backend to all processes when not specified. */
8668 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8669 if (curproxy->bind_proc)
8670 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008671 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008672 }
8673
8674 /*******************************************************/
8675 /* At this step, all proxies have a non-null bind_proc */
8676 /*******************************************************/
8677
8678 /* perform the final checks before creating tasks */
8679
8680 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8681 struct listener *listener;
8682 unsigned int next_id;
8683 int nbproc;
8684
David Carliere6c39412015-07-02 07:00:17 +00008685 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008686
Emeric Brunc52962f2012-11-15 18:28:02 +01008687#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008688 /* Configure SSL for each bind line.
8689 * Note: if configuration fails at some point, the ->ctx member
8690 * remains NULL so that listeners can later detach.
8691 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008692 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008693 int alloc_ctx;
8694
Emeric Brunc52962f2012-11-15 18:28:02 +01008695 if (!bind_conf->is_ssl) {
8696 if (bind_conf->default_ctx) {
8697 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8698 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8699 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008700 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008701 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008702 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008703 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008704 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008705 cfgerr++;
8706 continue;
8707 }
8708
Emeric Brun8dc60392014-05-09 13:52:00 +02008709 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008710 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008711 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8712 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");
8713 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008714 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008715 cfgerr++;
8716 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008717 }
8718
Emeric Brunfc0421f2012-09-07 17:30:07 +02008719 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008720 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008721
8722 /* initialize CA variables if the certificates generation is enabled */
8723 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008724 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008725#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008726
Willy Tarreaue6b98942007-10-29 01:09:36 +01008727 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008728 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008729 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008730 if (!listener->luid) {
8731 /* listener ID not set, use automatic numbering with first
8732 * spare entry starting with next_luid.
8733 */
8734 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8735 listener->conf.id.key = listener->luid = next_id;
8736 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008737 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008738 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008739
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008740 /* enable separate counters */
8741 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8742 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008743 if (!listener->name)
8744 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008745 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008746
Willy Tarreaue6b98942007-10-29 01:09:36 +01008747 if (curproxy->options & PR_O_TCP_NOLING)
8748 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008749 if (!listener->maxconn)
8750 listener->maxconn = curproxy->maxconn;
8751 if (!listener->backlog)
8752 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008753 if (!listener->maxaccept)
8754 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8755
8756 /* we want to have an optimal behaviour on single process mode to
8757 * maximize the work at once, but in multi-process we want to keep
8758 * some fairness between processes, so we target half of the max
8759 * number of events to be balanced over all the processes the proxy
8760 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8761 * used to disable the limit.
8762 */
8763 if (listener->maxaccept > 0) {
8764 if (nbproc > 1)
8765 listener->maxaccept = (listener->maxaccept + 1) / 2;
8766 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8767 }
8768
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008769 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008770 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008771 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008772 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008773
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008774 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8775 listener->options |= LI_O_TCP_RULES;
8776
Willy Tarreaude3041d2010-05-31 10:56:17 +02008777 if (curproxy->mon_mask.s_addr)
8778 listener->options |= LI_O_CHK_MONNET;
8779
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008780 /* smart accept mode is automatic in HTTP mode */
8781 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008782 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008783 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8784 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008785 }
8786
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008787 /* Release unused SSL configs */
8788 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8789 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008790 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008791#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008792 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008793 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008794 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008795 free(bind_conf->ca_sign_file);
8796 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008797 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008798 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008799 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008800 if(bind_conf->keys_ref) {
8801 free(bind_conf->keys_ref->filename);
8802 free(bind_conf->keys_ref->tlskeys);
8803 free(bind_conf->keys_ref);
8804 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008805#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008806 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008807
Willy Tarreau102df612014-05-07 23:56:38 +02008808 if (nbproc > 1) {
8809 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008810 int count, maxproc = 0;
8811
8812 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008813 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008814 if (count > maxproc)
8815 maxproc = count;
8816 }
8817 /* backends have 0, frontends have 1 or more */
8818 if (maxproc != 1)
8819 Warning("Proxy '%s': in multi-process mode, stats will be"
8820 " limited to process assigned to the current request.\n",
8821 curproxy->id);
8822
Willy Tarreau102df612014-05-07 23:56:38 +02008823 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8824 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8825 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008826 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008827 }
Willy Tarreau102df612014-05-07 23:56:38 +02008828 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8829 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8830 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008831 }
8832 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008833
8834 /* create the task associated with the proxy */
8835 curproxy->task = task_new();
8836 if (curproxy->task) {
8837 curproxy->task->context = curproxy;
8838 curproxy->task->process = manage_proxy;
8839 /* no need to queue, it will be done automatically if some
8840 * listener gets limited.
8841 */
8842 curproxy->task->expire = TICK_ETERNITY;
8843 } else {
8844 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8845 curproxy->id);
8846 cfgerr++;
8847 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008848 }
8849
Willy Tarreaufbb78422011-06-05 15:38:35 +02008850 /* automatically compute fullconn if not set. We must not do it in the
8851 * loop above because cross-references are not yet fully resolved.
8852 */
8853 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8854 /* If <fullconn> is not set, let's set it to 10% of the sum of
8855 * the possible incoming frontend's maxconns.
8856 */
8857 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8858 struct proxy *fe;
8859 int total = 0;
8860
8861 /* sum up the number of maxconns of frontends which
8862 * reference this backend at least once or which are
8863 * the same one ('listen').
8864 */
8865 for (fe = proxy; fe; fe = fe->next) {
8866 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008867 int found = 0;
8868
8869 if (!(fe->cap & PR_CAP_FE))
8870 continue;
8871
8872 if (fe == curproxy) /* we're on a "listen" instance */
8873 found = 1;
8874
8875 if (fe->defbe.be == curproxy) /* "default_backend" */
8876 found = 1;
8877
8878 /* check if a "use_backend" rule matches */
8879 if (!found) {
8880 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008881 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008882 found = 1;
8883 break;
8884 }
8885 }
8886 }
8887
Willy Tarreaufbb78422011-06-05 15:38:35 +02008888 /* now we've checked all possible ways to reference a backend
8889 * from a frontend.
8890 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008891 if (!found)
8892 continue;
8893 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008894 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008895 /* we have the sum of the maxconns in <total>. We only
8896 * keep 10% of that sum to set the default fullconn, with
8897 * a hard minimum of 1 (to avoid a divide by zero).
8898 */
8899 curproxy->fullconn = (total + 9) / 10;
8900 if (!curproxy->fullconn)
8901 curproxy->fullconn = 1;
8902 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008903 }
8904
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008905 /*
8906 * Recount currently required checks.
8907 */
8908
8909 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8910 int optnum;
8911
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008912 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8913 if (curproxy->options & cfg_opts[optnum].val)
8914 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008915
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008916 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8917 if (curproxy->options2 & cfg_opts2[optnum].val)
8918 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008919 }
8920
Willy Tarreau0fca4832015-05-01 19:12:05 +02008921 /* compute the required process bindings for the peers */
8922 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8923 if (curproxy->table.peers.p)
8924 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8925
Willy Tarreau122541c2011-09-07 21:24:49 +02008926 if (peers) {
8927 struct peers *curpeers = peers, **last;
8928 struct peer *p, *pb;
8929
Willy Tarreau1e273012015-05-01 19:15:17 +02008930 /* Remove all peers sections which don't have a valid listener,
8931 * which are not used by any table, or which are bound to more
8932 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008933 */
8934 last = &peers;
8935 while (*last) {
8936 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008937
8938 if (curpeers->state == PR_STSTOPPED) {
8939 /* the "disabled" keyword was present */
8940 if (curpeers->peers_fe)
8941 stop_proxy(curpeers->peers_fe);
8942 curpeers->peers_fe = NULL;
8943 }
8944 else if (!curpeers->peers_fe) {
8945 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8946 curpeers->id, localpeer);
8947 }
David Carliere6c39412015-07-02 07:00:17 +00008948 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008949 /* either it's totally stopped or too much used */
8950 if (curpeers->peers_fe->bind_proc) {
8951 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008952 "running in different processes (%d different ones). "
8953 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008954 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008955 cfgerr++;
8956 }
8957 stop_proxy(curpeers->peers_fe);
8958 curpeers->peers_fe = NULL;
8959 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008960 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008961 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008962 last = &curpeers->next;
8963 continue;
8964 }
8965
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008966 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008967 p = curpeers->remote;
8968 while (p) {
8969 pb = p->next;
8970 free(p->id);
8971 free(p);
8972 p = pb;
8973 }
8974
8975 /* Destroy and unlink this curpeers section.
8976 * Note: curpeers is backed up into *last.
8977 */
8978 free(curpeers->id);
8979 curpeers = curpeers->next;
8980 free(*last);
8981 *last = curpeers;
8982 }
8983 }
8984
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008985 /* initialize stick-tables on backend capable proxies. This must not
8986 * be done earlier because the data size may be discovered while parsing
8987 * other proxies.
8988 */
8989 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8990 if (curproxy->state == PR_STSTOPPED)
8991 continue;
8992
8993 if (!stktable_init(&curproxy->table)) {
8994 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8995 cfgerr++;
8996 }
8997 }
8998
Simon Horman0d16a402015-01-30 11:22:58 +09008999 if (mailers) {
9000 struct mailers *curmailers = mailers, **last;
9001 struct mailer *m, *mb;
9002
9003 /* Remove all mailers sections which don't have a valid listener.
9004 * This can happen when a mailers section is never referenced.
9005 */
9006 last = &mailers;
9007 while (*last) {
9008 curmailers = *last;
9009 if (curmailers->users) {
9010 last = &curmailers->next;
9011 continue;
9012 }
9013
9014 Warning("Removing incomplete section 'mailers %s'.\n",
9015 curmailers->id);
9016
9017 m = curmailers->mailer_list;
9018 while (m) {
9019 mb = m->next;
9020 free(m->id);
9021 free(m);
9022 m = mb;
9023 }
9024
9025 /* Destroy and unlink this curmailers section.
9026 * Note: curmailers is backed up into *last.
9027 */
9028 free(curmailers->id);
9029 curmailers = curmailers->next;
9030 free(*last);
9031 *last = curmailers;
9032 }
9033 }
9034
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009035 /* Update server_state_file_name to backend name if backend is supposed to use
9036 * a server-state file locally defined and none has been provided */
9037 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9038 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9039 curproxy->server_state_file_name == NULL)
9040 curproxy->server_state_file_name = strdup(curproxy->id);
9041 }
9042
Willy Tarreau34eb6712011-10-24 18:15:04 +02009043 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009044 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009045 MEM_F_SHARED);
9046
Willy Tarreaubb925012009-07-23 13:36:36 +02009047 if (cfgerr > 0)
9048 err_code |= ERR_ALERT | ERR_FATAL;
9049 out:
9050 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009051}
9052
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009053/*
9054 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9055 * parsing sessions.
9056 */
9057void cfg_register_keywords(struct cfg_kw_list *kwl)
9058{
9059 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9060}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009061
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009062/*
9063 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9064 */
9065void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9066{
9067 LIST_DEL(&kwl->list);
9068 LIST_INIT(&kwl->list);
9069}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009070
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009071/* this function register new section in the haproxy configuration file.
9072 * <section_name> is the name of this new section and <section_parser>
9073 * is the called parser. If two section declaration have the same name,
9074 * only the first declared is used.
9075 */
9076int cfg_register_section(char *section_name,
9077 int (*section_parser)(const char *, int, char **, int))
9078{
9079 struct cfg_section *cs;
9080
9081 cs = calloc(1, sizeof(*cs));
9082 if (!cs) {
9083 Alert("register section '%s': out of memory.\n", section_name);
9084 return 0;
9085 }
9086
9087 cs->section_name = section_name;
9088 cs->section_parser = section_parser;
9089
9090 LIST_ADDQ(&sections, &cs->list);
9091
9092 return 1;
9093}
9094
Willy Tarreaubaaee002006-06-26 02:48:02 +02009095/*
David Carlier845efb52015-09-25 11:49:18 +01009096 * free all config section entries
9097 */
9098void cfg_unregister_sections(void)
9099{
9100 struct cfg_section *cs, *ics;
9101
9102 list_for_each_entry_safe(cs, ics, &sections, list) {
9103 LIST_DEL(&cs->list);
9104 free(cs);
9105 }
9106}
9107
9108/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009109 * Local variables:
9110 * c-indent-level: 8
9111 * c-basic-offset: 8
9112 * End:
9113 */