blob: 22ff6af4a2b287428943048e1295c3bdf9cb1077 [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 Tarreaubaaee002006-06-26 02:48:02 +02001829 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001830 struct cfg_kw_list *kwl;
1831 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001832 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001833
1834 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1835 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1836 if (kwl->kw[index].section != CFG_GLOBAL)
1837 continue;
1838 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001839 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001840 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001841 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001842 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001843 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001844 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001845 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001846 err_code |= ERR_WARN;
1847 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001848 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001849 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001850 }
1851 }
1852 }
1853
Willy Tarreaubaaee002006-06-26 02:48:02 +02001854 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001855 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001856 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001857
Willy Tarreau058e9072009-07-20 09:30:05 +02001858 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001859 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001860 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001861}
1862
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001863void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001864{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001865 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001866 defproxy.mode = PR_MODE_TCP;
1867 defproxy.state = PR_STNEW;
1868 defproxy.maxconn = cfg_maxpconn;
1869 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001870 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001871
Simon Horman66183002013-02-23 10:16:43 +09001872 defproxy.defsrv.check.inter = DEF_CHKINTR;
1873 defproxy.defsrv.check.fastinter = 0;
1874 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001875 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1876 defproxy.defsrv.agent.fastinter = 0;
1877 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001878 defproxy.defsrv.check.rise = DEF_RISETIME;
1879 defproxy.defsrv.check.fall = DEF_FALLTIME;
1880 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1881 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001882 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001883 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001884 defproxy.defsrv.maxqueue = 0;
1885 defproxy.defsrv.minconn = 0;
1886 defproxy.defsrv.maxconn = 0;
1887 defproxy.defsrv.slowstart = 0;
1888 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1889 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1890 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001891
1892 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001893 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894}
1895
Willy Tarreauade5ec42010-01-28 19:33:49 +01001896
Willy Tarreau63af98d2014-05-18 08:11:41 +02001897/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1898 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1899 * ERR_FATAL in case of error.
1900 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001901static int create_cond_regex_rule(const char *file, int line,
1902 struct proxy *px, int dir, int action, int flags,
1903 const char *cmd, const char *reg, const char *repl,
1904 const char **cond_start)
1905{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001906 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001907 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001908 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001909 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001910 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001911 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001912 int cs;
1913 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001914
1915 if (px == &defproxy) {
1916 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001917 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001918 goto err;
1919 }
1920
1921 if (*reg == 0) {
1922 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001923 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001924 goto err;
1925 }
1926
1927 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001928 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001929
Willy Tarreau5321c422010-01-28 20:35:13 +01001930 if (cond_start &&
1931 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001932 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1933 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1934 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001935 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001936 goto err;
1937 }
1938 }
1939 else if (cond_start && **cond_start) {
1940 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1941 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001942 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001943 goto err;
1944 }
1945
Willy Tarreau63af98d2014-05-18 08:11:41 +02001946 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001947 (dir == SMP_OPT_DIR_REQ) ?
1948 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1949 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1950 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001951
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001952 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001953 if (!preg) {
1954 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001955 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001956 goto err;
1957 }
1958
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001959 cs = !(flags & REG_ICASE);
1960 cap = !(flags & REG_NOSUB);
1961 error = NULL;
1962 if (!regex_comp(reg, preg, cs, cap, &error)) {
1963 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1964 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001965 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001966 goto err;
1967 }
1968
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001969 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001970 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001971 if (repl && err) {
1972 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1973 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001974 ret_code |= ERR_ALERT | ERR_FATAL;
1975 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001976 }
1977
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001978 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001979 ret_code |= ERR_WARN;
1980
1981 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001982
Willy Tarreau63af98d2014-05-18 08:11:41 +02001983 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001984 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001985 err:
1986 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001987 free(errmsg);
1988 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001989}
1990
Willy Tarreaubaaee002006-06-26 02:48:02 +02001991/*
William Lallemand51097192015-04-14 16:35:22 +02001992 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001993 * Returns the error code, 0 if OK, or any combination of :
1994 * - ERR_ABORT: must abort ASAP
1995 * - ERR_FATAL: we can continue parsing but not start the service
1996 * - ERR_WARN: a warning has been emitted
1997 * - ERR_ALERT: an alert has been emitted
1998 * Only the two first ones can stop processing, the two others are just
1999 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002000 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002001int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2002{
2003 static struct peers *curpeers = NULL;
2004 struct peer *newpeer = NULL;
2005 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002006 struct bind_conf *bind_conf;
2007 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002008 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002009 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002010
2011 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002012 if (!*args[1]) {
2013 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002014 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002015 goto out;
2016 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002017
William Lallemand6e62fb62015-04-28 16:55:23 +02002018 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2019 goto out;
2020
Emeric Brun32da3c42010-09-23 18:39:19 +02002021 err = invalid_char(args[1]);
2022 if (err) {
2023 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2024 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002025 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002026 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002027 }
2028
2029 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2030 /*
2031 * If there are two proxies with the same name only following
2032 * combinations are allowed:
2033 */
2034 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002035 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 +02002036 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002037 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002038 }
2039 }
2040
2041 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
2042 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2043 err_code |= ERR_ALERT | ERR_ABORT;
2044 goto out;
2045 }
2046
2047 curpeers->next = peers;
2048 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002049 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002050 curpeers->conf.line = linenum;
2051 curpeers->last_change = now.tv_sec;
2052 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002053 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002054 }
2055 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002056 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002057 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002058 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002059
2060 if (!*args[2]) {
2061 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2062 file, linenum, args[0]);
2063 err_code |= ERR_ALERT | ERR_FATAL;
2064 goto out;
2065 }
2066
2067 err = invalid_char(args[1]);
2068 if (err) {
2069 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2070 file, linenum, *err, args[1]);
2071 err_code |= ERR_ALERT | ERR_FATAL;
2072 goto out;
2073 }
2074
2075 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2076 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2077 err_code |= ERR_ALERT | ERR_ABORT;
2078 goto out;
2079 }
2080
2081 /* the peers are linked backwards first */
2082 curpeers->count++;
2083 newpeer->next = curpeers->remote;
2084 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002085 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002086 newpeer->conf.line = linenum;
2087
2088 newpeer->last_change = now.tv_sec;
2089 newpeer->id = strdup(args[1]);
2090
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002091 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002092 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002093 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002094 err_code |= ERR_ALERT | ERR_FATAL;
2095 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002096 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002097
2098 proto = protocol_by_family(sk->ss_family);
2099 if (!proto || !proto->connect) {
2100 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2101 file, linenum, args[0], args[1]);
2102 err_code |= ERR_ALERT | ERR_FATAL;
2103 goto out;
2104 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002105
2106 if (port1 != port2) {
2107 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2108 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002109 err_code |= ERR_ALERT | ERR_FATAL;
2110 goto out;
2111 }
2112
Willy Tarreau2aa38802013-02-20 19:20:59 +01002113 if (!port1) {
2114 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2115 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002116 err_code |= ERR_ALERT | ERR_FATAL;
2117 goto out;
2118 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002119
Emeric Brun32da3c42010-09-23 18:39:19 +02002120 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002121 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002122 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002123 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002124
Emeric Brun32da3c42010-09-23 18:39:19 +02002125 if (strcmp(newpeer->id, localpeer) == 0) {
2126 /* Current is local peer, it define a frontend */
2127 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002128 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002129
2130 if (!curpeers->peers_fe) {
2131 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2132 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2133 err_code |= ERR_ALERT | ERR_ABORT;
2134 goto out;
2135 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002136
Willy Tarreau237250c2011-07-29 01:49:03 +02002137 init_new_proxy(curpeers->peers_fe);
2138 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002139 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002140 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2141 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002142 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002143
2144 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2145
Willy Tarreau902636f2013-03-10 19:44:48 +01002146 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2147 if (errmsg && *errmsg) {
2148 indent_msg(&errmsg, 2);
2149 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002150 }
2151 else
2152 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2153 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002154 err_code |= ERR_FATAL;
2155 goto out;
2156 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002157
2158 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002159 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002160 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2161 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002162 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002163 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002164 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002165 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002166 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2167 global.maxsock += l->maxconn;
2168 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002169 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002170 else {
2171 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2172 file, linenum, args[0], args[1],
2173 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2174 err_code |= ERR_FATAL;
2175 goto out;
2176 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002177 }
2178 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002179 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2180 curpeers->state = PR_STSTOPPED;
2181 }
2182 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2183 curpeers->state = PR_STNEW;
2184 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002185 else if (*args[0] != 0) {
2186 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2187 err_code |= ERR_ALERT | ERR_FATAL;
2188 goto out;
2189 }
2190
2191out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002192 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002193 return err_code;
2194}
2195
Baptiste Assmann325137d2015-04-13 23:40:55 +02002196/*
2197 * Parse a <resolvers> section.
2198 * Returns the error code, 0 if OK, or any combination of :
2199 * - ERR_ABORT: must abort ASAP
2200 * - ERR_FATAL: we can continue parsing but not start the service
2201 * - ERR_WARN: a warning has been emitted
2202 * - ERR_ALERT: an alert has been emitted
2203 * Only the two first ones can stop processing, the two others are just
2204 * indicators.
2205 */
2206int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2207{
2208 static struct dns_resolvers *curr_resolvers = NULL;
2209 struct dns_nameserver *newnameserver = NULL;
2210 const char *err;
2211 int err_code = 0;
2212 char *errmsg = NULL;
2213
2214 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2215 if (!*args[1]) {
2216 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2217 err_code |= ERR_ALERT | ERR_ABORT;
2218 goto out;
2219 }
2220
2221 err = invalid_char(args[1]);
2222 if (err) {
2223 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2224 file, linenum, *err, args[0], args[1]);
2225 err_code |= ERR_ALERT | ERR_ABORT;
2226 goto out;
2227 }
2228
2229 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2230 /* Error if two resolvers owns the same name */
2231 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2232 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2233 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2234 err_code |= ERR_ALERT | ERR_ABORT;
2235 }
2236 }
2237
2238 if ((curr_resolvers = (struct dns_resolvers *)calloc(1, sizeof(struct dns_resolvers))) == NULL) {
2239 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2240 err_code |= ERR_ALERT | ERR_ABORT;
2241 goto out;
2242 }
2243
2244 /* default values */
2245 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2246 curr_resolvers->conf.file = strdup(file);
2247 curr_resolvers->conf.line = linenum;
2248 curr_resolvers->id = strdup(args[1]);
2249 curr_resolvers->query_ids = EB_ROOT;
2250 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002251 curr_resolvers->hold.valid = 10000;
2252 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002253 curr_resolvers->resolve_retries = 3;
2254 LIST_INIT(&curr_resolvers->nameserver_list);
2255 LIST_INIT(&curr_resolvers->curr_resolution);
2256 }
2257 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2258 struct sockaddr_storage *sk;
2259 int port1, port2;
2260 struct protocol *proto;
2261
2262 if (!*args[2]) {
2263 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2264 file, linenum, args[0]);
2265 err_code |= ERR_ALERT | ERR_FATAL;
2266 goto out;
2267 }
2268
2269 err = invalid_char(args[1]);
2270 if (err) {
2271 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2272 file, linenum, *err, args[1]);
2273 err_code |= ERR_ALERT | ERR_FATAL;
2274 goto out;
2275 }
2276
Baptiste Assmanna315c552015-11-02 22:55:49 +01002277 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2278 /* Error if two resolvers owns the same name */
2279 if (strcmp(newnameserver->id, args[1]) == 0) {
2280 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2281 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2282 err_code |= ERR_ALERT | ERR_FATAL;
2283 }
2284 }
2285
Baptiste Assmann325137d2015-04-13 23:40:55 +02002286 if ((newnameserver = (struct dns_nameserver *)calloc(1, sizeof(struct dns_nameserver))) == NULL) {
2287 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2288 err_code |= ERR_ALERT | ERR_ABORT;
2289 goto out;
2290 }
2291
2292 /* the nameservers are linked backward first */
2293 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2294 curr_resolvers->count_nameservers++;
2295 newnameserver->resolvers = curr_resolvers;
2296 newnameserver->conf.file = strdup(file);
2297 newnameserver->conf.line = linenum;
2298 newnameserver->id = strdup(args[1]);
2299
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002300 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002301 if (!sk) {
2302 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2303 err_code |= ERR_ALERT | ERR_FATAL;
2304 goto out;
2305 }
2306
2307 proto = protocol_by_family(sk->ss_family);
2308 if (!proto || !proto->connect) {
2309 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2310 file, linenum, args[0], args[1]);
2311 err_code |= ERR_ALERT | ERR_FATAL;
2312 goto out;
2313 }
2314
2315 if (port1 != port2) {
2316 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2317 file, linenum, args[0], args[1], args[2]);
2318 err_code |= ERR_ALERT | ERR_FATAL;
2319 goto out;
2320 }
2321
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002322 if (!port1 && !port2) {
2323 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2324 file, linenum, args[0], args[1]);
2325 err_code |= ERR_ALERT | ERR_FATAL;
2326 goto out;
2327 }
2328
Baptiste Assmann325137d2015-04-13 23:40:55 +02002329 newnameserver->addr = *sk;
2330 }
2331 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2332 const char *res;
2333 unsigned int time;
2334
2335 if (!*args[2]) {
2336 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2337 file, linenum, args[0]);
2338 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
2341 }
2342 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2343 if (res) {
2344 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2345 file, linenum, *res, args[0]);
2346 err_code |= ERR_ALERT | ERR_FATAL;
2347 goto out;
2348 }
2349 if (strcmp(args[1], "valid") == 0)
2350 curr_resolvers->hold.valid = time;
2351 else {
2352 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2353 file, linenum, args[0], args[1]);
2354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
2356 }
2357
2358 }
2359 else if (strcmp(args[0], "resolve_retries") == 0) {
2360 if (!*args[1]) {
2361 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2362 file, linenum, args[0]);
2363 err_code |= ERR_ALERT | ERR_FATAL;
2364 goto out;
2365 }
2366 curr_resolvers->resolve_retries = atoi(args[1]);
2367 }
2368 else if (strcmp(args[0], "timeout") == 0) {
2369 const char *res;
2370 unsigned int timeout_retry;
2371
2372 if (!*args[2]) {
2373 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2374 file, linenum, args[0]);
2375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
2377 }
2378 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2379 if (res) {
2380 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2381 file, linenum, *res, args[0]);
2382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
2384 }
2385 curr_resolvers->timeout.retry = timeout_retry;
2386 } /* neither "nameserver" nor "resolvers" */
2387 else if (*args[0] != 0) {
2388 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2389 err_code |= ERR_ALERT | ERR_FATAL;
2390 goto out;
2391 }
2392
2393 out:
2394 free(errmsg);
2395 return err_code;
2396}
Simon Horman0d16a402015-01-30 11:22:58 +09002397
2398/*
William Lallemand51097192015-04-14 16:35:22 +02002399 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002400 * Returns the error code, 0 if OK, or any combination of :
2401 * - ERR_ABORT: must abort ASAP
2402 * - ERR_FATAL: we can continue parsing but not start the service
2403 * - ERR_WARN: a warning has been emitted
2404 * - ERR_ALERT: an alert has been emitted
2405 * Only the two first ones can stop processing, the two others are just
2406 * indicators.
2407 */
2408int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2409{
2410 static struct mailers *curmailers = NULL;
2411 struct mailer *newmailer = NULL;
2412 const char *err;
2413 int err_code = 0;
2414 char *errmsg = NULL;
2415
2416 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2417 if (!*args[1]) {
2418 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2419 err_code |= ERR_ALERT | ERR_ABORT;
2420 goto out;
2421 }
2422
2423 err = invalid_char(args[1]);
2424 if (err) {
2425 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2426 file, linenum, *err, args[0], args[1]);
2427 err_code |= ERR_ALERT | ERR_ABORT;
2428 goto out;
2429 }
2430
2431 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2432 /*
2433 * If there are two proxies with the same name only following
2434 * combinations are allowed:
2435 */
2436 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002437 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 +09002438 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002439 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002440 }
2441 }
2442
2443 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2444 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2445 err_code |= ERR_ALERT | ERR_ABORT;
2446 goto out;
2447 }
2448
2449 curmailers->next = mailers;
2450 mailers = curmailers;
2451 curmailers->conf.file = strdup(file);
2452 curmailers->conf.line = linenum;
2453 curmailers->id = strdup(args[1]);
2454 }
2455 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2456 struct sockaddr_storage *sk;
2457 int port1, port2;
2458 struct protocol *proto;
2459
2460 if (!*args[2]) {
2461 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2462 file, linenum, args[0]);
2463 err_code |= ERR_ALERT | ERR_FATAL;
2464 goto out;
2465 }
2466
2467 err = invalid_char(args[1]);
2468 if (err) {
2469 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2470 file, linenum, *err, args[1]);
2471 err_code |= ERR_ALERT | ERR_FATAL;
2472 goto out;
2473 }
2474
2475 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2476 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2477 err_code |= ERR_ALERT | ERR_ABORT;
2478 goto out;
2479 }
2480
2481 /* the mailers are linked backwards first */
2482 curmailers->count++;
2483 newmailer->next = curmailers->mailer_list;
2484 curmailers->mailer_list = newmailer;
2485 newmailer->mailers = curmailers;
2486 newmailer->conf.file = strdup(file);
2487 newmailer->conf.line = linenum;
2488
2489 newmailer->id = strdup(args[1]);
2490
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002491 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002492 if (!sk) {
2493 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2494 err_code |= ERR_ALERT | ERR_FATAL;
2495 goto out;
2496 }
2497
2498 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002499 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2500 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002501 file, linenum, args[0], args[1]);
2502 err_code |= ERR_ALERT | ERR_FATAL;
2503 goto out;
2504 }
2505
2506 if (port1 != port2) {
2507 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2508 file, linenum, args[0], args[1], args[2]);
2509 err_code |= ERR_ALERT | ERR_FATAL;
2510 goto out;
2511 }
2512
2513 if (!port1) {
2514 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2515 file, linenum, args[0], args[1], args[2]);
2516 err_code |= ERR_ALERT | ERR_FATAL;
2517 goto out;
2518 }
2519
2520 newmailer->addr = *sk;
2521 newmailer->proto = proto;
2522 newmailer->xprt = &raw_sock;
2523 newmailer->sock_init_arg = NULL;
2524 } /* neither "mailer" nor "mailers" */
2525 else if (*args[0] != 0) {
2526 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2527 err_code |= ERR_ALERT | ERR_FATAL;
2528 goto out;
2529 }
2530
2531out:
2532 free(errmsg);
2533 return err_code;
2534}
2535
Simon Horman9dc49962015-01-30 11:22:59 +09002536static void free_email_alert(struct proxy *p)
2537{
2538 free(p->email_alert.mailers.name);
2539 p->email_alert.mailers.name = NULL;
2540 free(p->email_alert.from);
2541 p->email_alert.from = NULL;
2542 free(p->email_alert.to);
2543 p->email_alert.to = NULL;
2544 free(p->email_alert.myhostname);
2545 p->email_alert.myhostname = NULL;
2546}
2547
Willy Tarreau3842f002009-06-14 11:39:52 +02002548int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549{
2550 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002551 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002552 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002553 int rc;
2554 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002555 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002556 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002557 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002558 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002559 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560
Willy Tarreau977b8e42006-12-29 14:19:17 +01002561 if (!strcmp(args[0], "listen"))
2562 rc = PR_CAP_LISTEN;
2563 else if (!strcmp(args[0], "frontend"))
2564 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002565 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002566 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002567 else
2568 rc = PR_CAP_NONE;
2569
2570 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 if (!*args[1]) {
2572 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2573 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2574 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002575 err_code |= ERR_ALERT | ERR_ABORT;
2576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002578
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002579 err = invalid_char(args[1]);
2580 if (err) {
2581 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2582 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002583 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002584 }
2585
Willy Tarreau8f50b682015-05-26 11:45:02 +02002586 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2587 if (curproxy) {
2588 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2589 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2590 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002591 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002592 }
2593
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2595 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002596 err_code |= ERR_ALERT | ERR_ABORT;
2597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002599
Willy Tarreau97cb7802010-01-03 20:23:58 +01002600 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002601 curproxy->next = proxy;
2602 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002603 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2604 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002605 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002606 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002607 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002608 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002609
William Lallemand6e62fb62015-04-28 16:55:23 +02002610 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2611 if (curproxy->cap & PR_CAP_FE)
2612 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 }
2615
2616 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002617 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002618 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002619
Willy Tarreaubaaee002006-06-26 02:48:02 +02002620 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002621 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002622 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002623 curproxy->no_options = defproxy.no_options;
2624 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002625 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002626 curproxy->except_net = defproxy.except_net;
2627 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002628 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002629 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002630
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002631 if (defproxy.fwdfor_hdr_len) {
2632 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2633 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2634 }
2635
Willy Tarreaub86db342009-11-30 11:50:16 +01002636 if (defproxy.orgto_hdr_len) {
2637 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2638 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2639 }
2640
Mark Lamourinec2247f02012-01-04 13:02:01 -05002641 if (defproxy.server_id_hdr_len) {
2642 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2643 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2644 }
2645
Willy Tarreau977b8e42006-12-29 14:19:17 +01002646 if (curproxy->cap & PR_CAP_FE) {
2647 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002648 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002649 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002650
2651 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002652 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2653 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002654
2655 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2656 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002657
Willy Tarreau977b8e42006-12-29 14:19:17 +01002658 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002659 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002660 curproxy->fullconn = defproxy.fullconn;
2661 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002662 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002663 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002664
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002665 if (defproxy.check_req) {
2666 curproxy->check_req = calloc(1, defproxy.check_len);
2667 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2668 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002669 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002670
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002671 if (defproxy.expect_str) {
2672 curproxy->expect_str = strdup(defproxy.expect_str);
2673 if (defproxy.expect_regex) {
2674 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002675 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2676 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002677 }
2678 }
2679
Willy Tarreau67402132012-05-31 20:40:20 +02002680 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002681 if (defproxy.cookie_name)
2682 curproxy->cookie_name = strdup(defproxy.cookie_name);
2683 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002684 if (defproxy.cookie_domain)
2685 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002686
Willy Tarreau31936852010-10-06 16:59:56 +02002687 if (defproxy.cookie_maxidle)
2688 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2689
2690 if (defproxy.cookie_maxlife)
2691 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2692
Emeric Brun647caf12009-06-30 17:57:00 +02002693 if (defproxy.rdp_cookie_name)
2694 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2695 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2696
Willy Tarreau01732802007-11-01 22:48:15 +01002697 if (defproxy.url_param_name)
2698 curproxy->url_param_name = strdup(defproxy.url_param_name);
2699 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002700
Benoitaffb4812009-03-25 13:02:10 +01002701 if (defproxy.hh_name)
2702 curproxy->hh_name = strdup(defproxy.hh_name);
2703 curproxy->hh_len = defproxy.hh_len;
2704 curproxy->hh_match_domain = defproxy.hh_match_domain;
2705
Willy Tarreauef9a3602012-12-08 22:29:20 +01002706 if (defproxy.conn_src.iface_name)
2707 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2708 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002709 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002710#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002711 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002712#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002713 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002714 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002715
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002716 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002717 if (defproxy.capture_name)
2718 curproxy->capture_name = strdup(defproxy.capture_name);
2719 curproxy->capture_namelen = defproxy.capture_namelen;
2720 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002722
Willy Tarreau977b8e42006-12-29 14:19:17 +01002723 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002724 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002725 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002726 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002727 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002728 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002729 curproxy->mon_net = defproxy.mon_net;
2730 curproxy->mon_mask = defproxy.mon_mask;
2731 if (defproxy.monitor_uri)
2732 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2733 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002734 if (defproxy.defbe.name)
2735 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002736
2737 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002738 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2739 if (curproxy->conf.logformat_string &&
2740 curproxy->conf.logformat_string != default_http_log_format &&
2741 curproxy->conf.logformat_string != default_tcp_log_format &&
2742 curproxy->conf.logformat_string != clf_http_log_format)
2743 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2744
2745 if (defproxy.conf.lfs_file) {
2746 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2747 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2748 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002749
2750 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2751 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2752 if (curproxy->conf.logformat_sd_string &&
2753 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2754 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2755
2756 if (defproxy.conf.lfsd_file) {
2757 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2758 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2759 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002760 }
2761
2762 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002763 curproxy->timeout.connect = defproxy.timeout.connect;
2764 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002765 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002766 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002767 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002768 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002769 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002770 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002771 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002772 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002773 }
2774
Willy Tarreaubaaee002006-06-26 02:48:02 +02002775 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002776 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002777
2778 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002779 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002780 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002781 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002782 LIST_INIT(&node->list);
2783 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2784 }
2785
Willy Tarreau62a61232013-04-12 18:13:46 +02002786 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2787 if (curproxy->conf.uniqueid_format_string)
2788 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2789
Dragan Dosen43885c72015-10-01 13:18:13 +02002790 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002791
Willy Tarreau62a61232013-04-12 18:13:46 +02002792 if (defproxy.conf.uif_file) {
2793 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2794 curproxy->conf.uif_line = defproxy.conf.uif_line;
2795 }
William Lallemanda73203e2012-03-12 12:48:57 +01002796
2797 /* copy default header unique id */
2798 if (defproxy.header_unique_id)
2799 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2800
William Lallemand82fe75c2012-10-23 10:25:10 +02002801 /* default compression options */
2802 if (defproxy.comp != NULL) {
2803 curproxy->comp = calloc(1, sizeof(struct comp));
2804 curproxy->comp->algos = defproxy.comp->algos;
2805 curproxy->comp->types = defproxy.comp->types;
2806 }
2807
Willy Tarreaubaaee002006-06-26 02:48:02 +02002808 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002809 curproxy->conf.used_listener_id = EB_ROOT;
2810 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002811
Simon Horman98637e52014-06-20 12:30:16 +09002812 if (defproxy.check_path)
2813 curproxy->check_path = strdup(defproxy.check_path);
2814 if (defproxy.check_command)
2815 curproxy->check_command = strdup(defproxy.check_command);
2816
Simon Horman9dc49962015-01-30 11:22:59 +09002817 if (defproxy.email_alert.mailers.name)
2818 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2819 if (defproxy.email_alert.from)
2820 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2821 if (defproxy.email_alert.to)
2822 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2823 if (defproxy.email_alert.myhostname)
2824 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002825 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002826 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002827
Willy Tarreau93893792009-07-23 13:19:11 +02002828 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002829 }
2830 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2831 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002832 /* FIXME-20070101: we should do this too at the end of the
2833 * config parsing to free all default values.
2834 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002835 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2836 err_code |= ERR_ABORT;
2837 goto out;
2838 }
2839
Willy Tarreaua534fea2008-08-03 12:19:50 +02002840 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002841 free(defproxy.check_command);
2842 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002843 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002844 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002845 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002846 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002847 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002848 free(defproxy.capture_name);
2849 free(defproxy.monitor_uri);
2850 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002851 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002852 free(defproxy.fwdfor_hdr_name);
2853 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002854 free(defproxy.orgto_hdr_name);
2855 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002856 free(defproxy.server_id_hdr_name);
2857 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002858 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002859 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002860 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002861 free(defproxy.expect_regex);
2862 defproxy.expect_regex = NULL;
2863 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002864
Willy Tarreau62a61232013-04-12 18:13:46 +02002865 if (defproxy.conf.logformat_string != default_http_log_format &&
2866 defproxy.conf.logformat_string != default_tcp_log_format &&
2867 defproxy.conf.logformat_string != clf_http_log_format)
2868 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002869
Willy Tarreau62a61232013-04-12 18:13:46 +02002870 free(defproxy.conf.uniqueid_format_string);
2871 free(defproxy.conf.lfs_file);
2872 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002873 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002874 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002875
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002876 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2877 free(defproxy.conf.logformat_sd_string);
2878 free(defproxy.conf.lfsd_file);
2879
Willy Tarreaua534fea2008-08-03 12:19:50 +02002880 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002881 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002882
Willy Tarreaubaaee002006-06-26 02:48:02 +02002883 /* we cannot free uri_auth because it might already be used */
2884 init_default_instance();
2885 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002886 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2887 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002888 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002889 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 }
2891 else if (curproxy == NULL) {
2892 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002895 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002896
2897 /* update the current file and line being parsed */
2898 curproxy->conf.args.file = curproxy->conf.file;
2899 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002900
2901 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002902 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2903 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2904 if (err_code & ERR_FATAL)
2905 goto out;
2906 }
2907 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002908 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002909 int cur_arg;
2910
Willy Tarreaubaaee002006-06-26 02:48:02 +02002911 if (curproxy == &defproxy) {
2912 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002916 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002917 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002918
Willy Tarreau24709282013-03-10 21:32:12 +01002919 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002920 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002921 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002924 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002925
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002926 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002927
2928 /* use default settings for unix sockets */
2929 bind_conf->ux.uid = global.unix_bind.ux.uid;
2930 bind_conf->ux.gid = global.unix_bind.ux.gid;
2931 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002932
2933 /* NOTE: the following line might create several listeners if there
2934 * are comma-separated IPs or port ranges. So all further processing
2935 * will have to be applied to all listeners created after last_listen.
2936 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002937 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2938 if (errmsg && *errmsg) {
2939 indent_msg(&errmsg, 2);
2940 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002941 }
2942 else
2943 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2944 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002945 err_code |= ERR_ALERT | ERR_FATAL;
2946 goto out;
2947 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002948
Willy Tarreau4348fad2012-09-20 16:48:07 +02002949 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2950 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002951 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002952 }
2953
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002954 cur_arg = 2;
2955 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002956 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002957 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002958 char *err;
2959
Willy Tarreau26982662012-09-12 23:17:10 +02002960 kw = bind_find_kw(args[cur_arg]);
2961 if (kw) {
2962 char *err = NULL;
2963 int code;
2964
2965 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002966 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2967 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002968 cur_arg += 1 + kw->skip ;
2969 err_code |= ERR_ALERT | ERR_FATAL;
2970 goto out;
2971 }
2972
Willy Tarreau4348fad2012-09-20 16:48:07 +02002973 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002974 err_code |= code;
2975
2976 if (code) {
2977 if (err && *err) {
2978 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002979 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002980 }
2981 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002982 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2983 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002984 if (code & ERR_FATAL) {
2985 free(err);
2986 cur_arg += 1 + kw->skip;
2987 goto out;
2988 }
2989 }
2990 free(err);
2991 cur_arg += 1 + kw->skip;
2992 continue;
2993 }
2994
Willy Tarreau8638f482012-09-18 18:01:17 +02002995 err = NULL;
2996 if (!bind_dumped) {
2997 bind_dump_kws(&err);
2998 indent_msg(&err, 4);
2999 bind_dumped = 1;
3000 }
3001
3002 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3003 file, linenum, args[0], args[1], args[cur_arg],
3004 err ? " Registered keywords :" : "", err ? err : "");
3005 free(err);
3006
Willy Tarreau93893792009-07-23 13:19:11 +02003007 err_code |= ERR_ALERT | ERR_FATAL;
3008 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003009 }
Willy Tarreau93893792009-07-23 13:19:11 +02003010 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003011 }
3012 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003013 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3015 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003016 err_code |= ERR_ALERT | ERR_FATAL;
3017 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003018 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003019 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003020 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003021
Willy Tarreaubaaee002006-06-26 02:48:02 +02003022 /* flush useless bits */
3023 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003025 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003026 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003027 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003028 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003029
William Lallemanddf1425a2015-04-28 20:17:49 +02003030 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3031 goto out;
3032
Willy Tarreau1c47f852006-07-09 08:22:27 +02003033 if (!*args[1]) {
3034 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3035 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003038 }
3039
Willy Tarreaua534fea2008-08-03 12:19:50 +02003040 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003041 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003042 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003043 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003044 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3045
Willy Tarreau93893792009-07-23 13:19:11 +02003046 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003047 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003048 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003049 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3050 goto out;
3051
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3053 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3054 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3055 else {
3056 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003057 err_code |= ERR_ALERT | ERR_FATAL;
3058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003059 }
3060 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003061 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003062 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003063
3064 if (curproxy == &defproxy) {
3065 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3066 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003067 err_code |= ERR_ALERT | ERR_FATAL;
3068 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003069 }
3070
William Lallemanddf1425a2015-04-28 20:17:49 +02003071 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3072 goto out;
3073
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003074 if (!*args[1]) {
3075 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3076 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003077 err_code |= ERR_ALERT | ERR_FATAL;
3078 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003079 }
3080
3081 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003082 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003083 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003084
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003085 if (curproxy->uuid <= 0) {
3086 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003087 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003088 err_code |= ERR_ALERT | ERR_FATAL;
3089 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003090 }
3091
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003092 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3093 if (node) {
3094 struct proxy *target = container_of(node, struct proxy, conf.id);
3095 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3096 file, linenum, proxy_type_str(curproxy), curproxy->id,
3097 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3098 err_code |= ERR_ALERT | ERR_FATAL;
3099 goto out;
3100 }
3101 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003102 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003103 else if (!strcmp(args[0], "description")) {
3104 int i, len=0;
3105 char *d;
3106
Cyril Bonté99ed3272010-01-24 23:29:44 +01003107 if (curproxy == &defproxy) {
3108 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3109 file, linenum, args[0]);
3110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
3112 }
3113
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003114 if (!*args[1]) {
3115 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3116 file, linenum, args[0]);
3117 return -1;
3118 }
3119
Willy Tarreau348acfe2014-04-14 15:00:39 +02003120 for (i = 1; *args[i]; i++)
3121 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003122
3123 d = (char *)calloc(1, len);
3124 curproxy->desc = d;
3125
Willy Tarreau348acfe2014-04-14 15:00:39 +02003126 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3127 for (i = 2; *args[i]; i++)
3128 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003129
3130 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003132 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3133 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003134 curproxy->state = PR_STSTOPPED;
3135 }
3136 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003137 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003139 curproxy->state = PR_STNEW;
3140 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003141 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3142 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003143 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003144
3145 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003146 unsigned int low, high;
3147
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003148 if (strcmp(args[cur_arg], "all") == 0) {
3149 set = 0;
3150 break;
3151 }
3152 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003153 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003154 }
3155 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003156 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003157 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003158 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003159 char *dash = strchr(args[cur_arg], '-');
3160
3161 low = high = str2uic(args[cur_arg]);
3162 if (dash)
3163 high = str2uic(dash + 1);
3164
3165 if (high < low) {
3166 unsigned int swap = low;
3167 low = high;
3168 high = swap;
3169 }
3170
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003171 if (low < 1 || high > LONGBITS) {
3172 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3173 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003176 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003177 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003178 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003179 }
3180 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003181 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3182 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003183 err_code |= ERR_ALERT | ERR_FATAL;
3184 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003185 }
3186 cur_arg++;
3187 }
3188 curproxy->bind_proc = set;
3189 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003190 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003191 if (curproxy == &defproxy) {
3192 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003193 err_code |= ERR_ALERT | ERR_FATAL;
3194 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003195 }
3196
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003197 err = invalid_char(args[1]);
3198 if (err) {
3199 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3200 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003201 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003202 }
3203
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003204 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003205 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3206 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003207 err_code |= ERR_ALERT | ERR_FATAL;
3208 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003209 }
3210 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3212 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003213
Willy Tarreau977b8e42006-12-29 14:19:17 +01003214 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003215 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003216
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 if (*(args[1]) == 0) {
3218 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3219 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003220 err_code |= ERR_ALERT | ERR_FATAL;
3221 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003223
Willy Tarreau67402132012-05-31 20:40:20 +02003224 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003225 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003226 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003227 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 curproxy->cookie_name = strdup(args[1]);
3229 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003230
Willy Tarreaubaaee002006-06-26 02:48:02 +02003231 cur_arg = 2;
3232 while (*(args[cur_arg])) {
3233 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003234 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003235 }
3236 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003237 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 }
3239 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003240 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 }
3242 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003243 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003244 }
3245 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003246 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003247 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003248 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003249 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003251 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003252 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003253 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003254 else if (!strcmp(args[cur_arg], "httponly")) {
3255 curproxy->ck_opts |= PR_CK_HTTPONLY;
3256 }
3257 else if (!strcmp(args[cur_arg], "secure")) {
3258 curproxy->ck_opts |= PR_CK_SECURE;
3259 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003260 else if (!strcmp(args[cur_arg], "domain")) {
3261 if (!*args[cur_arg + 1]) {
3262 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3263 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003264 err_code |= ERR_ALERT | ERR_FATAL;
3265 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003266 }
3267
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003268 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003269 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003270 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3271 " dots nor does not start with a dot."
3272 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003273 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003274 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003275 }
3276
3277 err = invalid_domainchar(args[cur_arg + 1]);
3278 if (err) {
3279 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3280 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003281 err_code |= ERR_ALERT | ERR_FATAL;
3282 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003283 }
3284
Willy Tarreau68a897b2009-12-03 23:28:34 +01003285 if (!curproxy->cookie_domain) {
3286 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3287 } else {
3288 /* one domain was already specified, add another one by
3289 * building the string which will be returned along with
3290 * the cookie.
3291 */
3292 char *new_ptr;
3293 int new_len = strlen(curproxy->cookie_domain) +
3294 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3295 new_ptr = malloc(new_len);
3296 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3297 free(curproxy->cookie_domain);
3298 curproxy->cookie_domain = new_ptr;
3299 }
Willy Tarreau31936852010-10-06 16:59:56 +02003300 cur_arg++;
3301 }
3302 else if (!strcmp(args[cur_arg], "maxidle")) {
3303 unsigned int maxidle;
3304 const char *res;
3305
3306 if (!*args[cur_arg + 1]) {
3307 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3308 file, linenum, args[cur_arg]);
3309 err_code |= ERR_ALERT | ERR_FATAL;
3310 goto out;
3311 }
3312
3313 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3314 if (res) {
3315 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3316 file, linenum, *res, args[cur_arg]);
3317 err_code |= ERR_ALERT | ERR_FATAL;
3318 goto out;
3319 }
3320 curproxy->cookie_maxidle = maxidle;
3321 cur_arg++;
3322 }
3323 else if (!strcmp(args[cur_arg], "maxlife")) {
3324 unsigned int maxlife;
3325 const char *res;
3326
3327 if (!*args[cur_arg + 1]) {
3328 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3329 file, linenum, args[cur_arg]);
3330 err_code |= ERR_ALERT | ERR_FATAL;
3331 goto out;
3332 }
3333
3334 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3335 if (res) {
3336 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3337 file, linenum, *res, args[cur_arg]);
3338 err_code |= ERR_ALERT | ERR_FATAL;
3339 goto out;
3340 }
3341 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003342 cur_arg++;
3343 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003344 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003345 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 +02003346 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003349 }
3350 cur_arg++;
3351 }
Willy Tarreau67402132012-05-31 20:40:20 +02003352 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3354 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003355 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 }
3357
Willy Tarreau67402132012-05-31 20:40:20 +02003358 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3360 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003361 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003362 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003363
Willy Tarreau67402132012-05-31 20:40:20 +02003364 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003365 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3366 file, linenum);
3367 err_code |= ERR_ALERT | ERR_FATAL;
3368 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003370 else if (!strcmp(args[0], "email-alert")) {
3371 if (*(args[1]) == 0) {
3372 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3373 file, linenum, args[0]);
3374 err_code |= ERR_ALERT | ERR_FATAL;
3375 goto out;
3376 }
3377
3378 if (!strcmp(args[1], "from")) {
3379 if (*(args[1]) == 0) {
3380 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3381 file, linenum, args[1]);
3382 err_code |= ERR_ALERT | ERR_FATAL;
3383 goto out;
3384 }
3385 free(curproxy->email_alert.from);
3386 curproxy->email_alert.from = strdup(args[2]);
3387 }
3388 else if (!strcmp(args[1], "mailers")) {
3389 if (*(args[1]) == 0) {
3390 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3391 file, linenum, args[1]);
3392 err_code |= ERR_ALERT | ERR_FATAL;
3393 goto out;
3394 }
3395 free(curproxy->email_alert.mailers.name);
3396 curproxy->email_alert.mailers.name = strdup(args[2]);
3397 }
3398 else if (!strcmp(args[1], "myhostname")) {
3399 if (*(args[1]) == 0) {
3400 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3401 file, linenum, args[1]);
3402 err_code |= ERR_ALERT | ERR_FATAL;
3403 goto out;
3404 }
3405 free(curproxy->email_alert.myhostname);
3406 curproxy->email_alert.myhostname = strdup(args[2]);
3407 }
Simon Horman64e34162015-02-06 11:11:57 +09003408 else if (!strcmp(args[1], "level")) {
3409 curproxy->email_alert.level = get_log_level(args[2]);
3410 if (curproxy->email_alert.level < 0) {
3411 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3412 file, linenum, args[1], args[2]);
3413 err_code |= ERR_ALERT | ERR_FATAL;
3414 goto out;
3415 }
3416 }
Simon Horman9dc49962015-01-30 11:22:59 +09003417 else if (!strcmp(args[1], "to")) {
3418 if (*(args[1]) == 0) {
3419 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3420 file, linenum, args[1]);
3421 err_code |= ERR_ALERT | ERR_FATAL;
3422 goto out;
3423 }
3424 free(curproxy->email_alert.to);
3425 curproxy->email_alert.to = strdup(args[2]);
3426 }
3427 else {
3428 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3429 file, linenum, args[1]);
3430 err_code |= ERR_ALERT | ERR_FATAL;
3431 goto out;
3432 }
Simon Horman64e34162015-02-06 11:11:57 +09003433 /* Indicate that the email_alert is at least partially configured */
3434 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003435 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003436 else if (!strcmp(args[0], "external-check")) {
3437 if (*(args[1]) == 0) {
3438 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3439 file, linenum, args[0]);
3440 err_code |= ERR_ALERT | ERR_FATAL;
3441 goto out;
3442 }
3443
3444 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003445 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003446 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003447 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003448 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3449 file, linenum, args[1]);
3450 err_code |= ERR_ALERT | ERR_FATAL;
3451 goto out;
3452 }
3453 free(curproxy->check_command);
3454 curproxy->check_command = strdup(args[2]);
3455 }
3456 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003457 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003458 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003459 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003460 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3461 file, linenum, args[1]);
3462 err_code |= ERR_ALERT | ERR_FATAL;
3463 goto out;
3464 }
3465 free(curproxy->check_path);
3466 curproxy->check_path = strdup(args[2]);
3467 }
3468 else {
3469 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3470 file, linenum, args[1]);
3471 err_code |= ERR_ALERT | ERR_FATAL;
3472 goto out;
3473 }
3474 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003475 else if (!strcmp(args[0], "persist")) { /* persist */
3476 if (*(args[1]) == 0) {
3477 Alert("parsing [%s:%d] : missing persist method.\n",
3478 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003479 err_code |= ERR_ALERT | ERR_FATAL;
3480 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003481 }
3482
3483 if (!strncmp(args[1], "rdp-cookie", 10)) {
3484 curproxy->options2 |= PR_O2_RDPC_PRST;
3485
Emeric Brunb982a3d2010-01-04 15:45:53 +01003486 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003487 const char *beg, *end;
3488
3489 beg = args[1] + 11;
3490 end = strchr(beg, ')');
3491
William Lallemanddf1425a2015-04-28 20:17:49 +02003492 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3493 goto out;
3494
Emeric Brun647caf12009-06-30 17:57:00 +02003495 if (!end || end == beg) {
3496 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3497 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003500 }
3501
3502 free(curproxy->rdp_cookie_name);
3503 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3504 curproxy->rdp_cookie_len = end-beg;
3505 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003506 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003507 free(curproxy->rdp_cookie_name);
3508 curproxy->rdp_cookie_name = strdup("msts");
3509 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3510 }
3511 else { /* syntax */
3512 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3513 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003514 err_code |= ERR_ALERT | ERR_FATAL;
3515 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003516 }
3517 }
3518 else {
3519 Alert("parsing [%s:%d] : unknown persist method.\n",
3520 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003521 err_code |= ERR_ALERT | ERR_FATAL;
3522 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003523 }
3524 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003525 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003526 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3527 err_code |= ERR_ALERT | ERR_FATAL;
3528 goto out;
3529 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003530 else if (!strcmp(args[0], "load-server-state-from-file")) {
3531 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3532 err_code |= ERR_WARN;
3533 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3534 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3535 }
3536 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3537 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3538 }
3539 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3540 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3541 }
3542 else {
3543 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3544 file, linenum, args[0], args[1]);
3545 err_code |= ERR_ALERT | ERR_FATAL;
3546 goto out;
3547 }
3548 }
3549 else if (!strcmp(args[0], "server-state-file-name")) {
3550 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3551 err_code |= ERR_WARN;
3552 if (*(args[1]) == 0) {
3553 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3554 file, linenum, args[0]);
3555 err_code |= ERR_ALERT | ERR_FATAL;
3556 goto out;
3557 }
3558 else if (!strcmp(args[1], "use-backend-name"))
3559 curproxy->server_state_file_name = strdup(curproxy->id);
3560 else
3561 curproxy->server_state_file_name = strdup(args[1]);
3562 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003563 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003564 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003565 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003566
Willy Tarreaubaaee002006-06-26 02:48:02 +02003567 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003568 if (curproxy == &defproxy) {
3569 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3570 err_code |= ERR_ALERT | ERR_FATAL;
3571 goto out;
3572 }
3573
William Lallemand1a748ae2015-05-19 16:37:23 +02003574 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3575 goto out;
3576
Willy Tarreaubaaee002006-06-26 02:48:02 +02003577 if (*(args[4]) == 0) {
3578 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3579 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003580 err_code |= ERR_ALERT | ERR_FATAL;
3581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003583 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003584 curproxy->capture_name = strdup(args[2]);
3585 curproxy->capture_namelen = strlen(curproxy->capture_name);
3586 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003587 curproxy->to_log |= LW_COOKIE;
3588 }
3589 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3590 struct cap_hdr *hdr;
3591
3592 if (curproxy == &defproxy) {
3593 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 +02003594 err_code |= ERR_ALERT | ERR_FATAL;
3595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003596 }
3597
William Lallemand1a748ae2015-05-19 16:37:23 +02003598 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3599 goto out;
3600
Willy Tarreaubaaee002006-06-26 02:48:02 +02003601 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3602 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3603 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003606 }
3607
3608 hdr = calloc(sizeof(struct cap_hdr), 1);
3609 hdr->next = curproxy->req_cap;
3610 hdr->name = strdup(args[3]);
3611 hdr->namelen = strlen(args[3]);
3612 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003613 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003614 hdr->index = curproxy->nb_req_cap++;
3615 curproxy->req_cap = hdr;
3616 curproxy->to_log |= LW_REQHDR;
3617 }
3618 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3619 struct cap_hdr *hdr;
3620
3621 if (curproxy == &defproxy) {
3622 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 +02003623 err_code |= ERR_ALERT | ERR_FATAL;
3624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003625 }
3626
William Lallemand1a748ae2015-05-19 16:37:23 +02003627 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3628 goto out;
3629
Willy Tarreaubaaee002006-06-26 02:48:02 +02003630 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3631 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3632 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003635 }
3636 hdr = calloc(sizeof(struct cap_hdr), 1);
3637 hdr->next = curproxy->rsp_cap;
3638 hdr->name = strdup(args[3]);
3639 hdr->namelen = strlen(args[3]);
3640 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003641 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 hdr->index = curproxy->nb_rsp_cap++;
3643 curproxy->rsp_cap = hdr;
3644 curproxy->to_log |= LW_RSPHDR;
3645 }
3646 else {
3647 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3648 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 }
3652 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003653 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003654 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003655 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003656
William Lallemanddf1425a2015-04-28 20:17:49 +02003657 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3658 goto out;
3659
Willy Tarreaubaaee002006-06-26 02:48:02 +02003660 if (*(args[1]) == 0) {
3661 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3662 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003665 }
3666 curproxy->conn_retries = atol(args[1]);
3667 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003668 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003669 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003670
3671 if (curproxy == &defproxy) {
3672 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
3675 }
3676
Willy Tarreau20b0de52012-12-24 15:45:22 +01003677 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003678 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003679 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3680 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3681 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3682 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003683 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 +01003684 file, linenum, args[0]);
3685 err_code |= ERR_WARN;
3686 }
3687
Willy Tarreauff011f22011-01-06 17:51:27 +01003688 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003689
Willy Tarreauff011f22011-01-06 17:51:27 +01003690 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003691 err_code |= ERR_ALERT | ERR_ABORT;
3692 goto out;
3693 }
3694
Willy Tarreau5002f572014-04-23 01:32:02 +02003695 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003696 err_code |= warnif_cond_conflicts(rule->cond,
3697 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3698 file, linenum);
3699
Willy Tarreauff011f22011-01-06 17:51:27 +01003700 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003701 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003702 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003703 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003704
3705 if (curproxy == &defproxy) {
3706 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3707 err_code |= ERR_ALERT | ERR_FATAL;
3708 goto out;
3709 }
3710
3711 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003712 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003713 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3714 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003715 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3716 file, linenum, args[0]);
3717 err_code |= ERR_WARN;
3718 }
3719
3720 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3721
3722 if (!rule) {
3723 err_code |= ERR_ALERT | ERR_ABORT;
3724 goto out;
3725 }
3726
3727 err_code |= warnif_cond_conflicts(rule->cond,
3728 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3729 file, linenum);
3730
3731 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3732 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003733 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3734 /* set the header name and length into the proxy structure */
3735 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3736 err_code |= ERR_WARN;
3737
3738 if (!*args[1]) {
3739 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3740 file, linenum, args[0]);
3741 err_code |= ERR_ALERT | ERR_FATAL;
3742 goto out;
3743 }
3744
3745 /* set the desired header name */
3746 free(curproxy->server_id_hdr_name);
3747 curproxy->server_id_hdr_name = strdup(args[1]);
3748 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3749 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003750 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003751 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003752
Willy Tarreaub099aca2008-10-12 17:26:37 +02003753 if (curproxy == &defproxy) {
3754 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003755 err_code |= ERR_ALERT | ERR_FATAL;
3756 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003757 }
3758
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003759 /* emulate "block" using "http-request block". Since these rules are supposed to
3760 * be processed before all http-request rules, we put them into their own list
3761 * and will insert them at the end.
3762 */
3763 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3764 if (!rule) {
3765 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003766 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003767 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003768 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3769 err_code |= warnif_cond_conflicts(rule->cond,
3770 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3771 file, linenum);
3772 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003773
3774 if (!already_warned(WARN_BLOCK_DEPRECATED))
3775 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]);
3776
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003777 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003778 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003779 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003780
Cyril Bonté99ed3272010-01-24 23:29:44 +01003781 if (curproxy == &defproxy) {
3782 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3783 err_code |= ERR_ALERT | ERR_FATAL;
3784 goto out;
3785 }
3786
Willy Tarreaube4653b2015-05-28 15:26:58 +02003787 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003788 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3789 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003790 err_code |= ERR_ALERT | ERR_FATAL;
3791 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003792 }
3793
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003794 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003795 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003796 err_code |= warnif_cond_conflicts(rule->cond,
3797 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3798 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003799 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003800 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003801 struct switching_rule *rule;
3802
Willy Tarreaub099aca2008-10-12 17:26:37 +02003803 if (curproxy == &defproxy) {
3804 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003805 err_code |= ERR_ALERT | ERR_FATAL;
3806 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003807 }
3808
Willy Tarreau55ea7572007-06-17 19:56:27 +02003809 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003810 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003811
3812 if (*(args[1]) == 0) {
3813 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003814 err_code |= ERR_ALERT | ERR_FATAL;
3815 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003816 }
3817
Willy Tarreauf51658d2014-04-23 01:21:56 +02003818 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3819 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3820 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3821 file, linenum, errmsg);
3822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
3824 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003825
Willy Tarreauf51658d2014-04-23 01:21:56 +02003826 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003827 }
3828
3829 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3830 rule->cond = cond;
3831 rule->be.name = strdup(args[1]);
3832 LIST_INIT(&rule->list);
3833 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3834 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003835 else if (strcmp(args[0], "use-server") == 0) {
3836 struct server_rule *rule;
3837
3838 if (curproxy == &defproxy) {
3839 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
3842 }
3843
3844 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3845 err_code |= ERR_WARN;
3846
3847 if (*(args[1]) == 0) {
3848 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3849 err_code |= ERR_ALERT | ERR_FATAL;
3850 goto out;
3851 }
3852
3853 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3854 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3855 file, linenum, args[0]);
3856 err_code |= ERR_ALERT | ERR_FATAL;
3857 goto out;
3858 }
3859
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003860 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3861 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3862 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003863 err_code |= ERR_ALERT | ERR_FATAL;
3864 goto out;
3865 }
3866
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003867 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003868
3869 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3870 rule->cond = cond;
3871 rule->srv.name = strdup(args[1]);
3872 LIST_INIT(&rule->list);
3873 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3874 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3875 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003876 else if ((!strcmp(args[0], "force-persist")) ||
3877 (!strcmp(args[0], "ignore-persist"))) {
3878 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003879
3880 if (curproxy == &defproxy) {
3881 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3882 err_code |= ERR_ALERT | ERR_FATAL;
3883 goto out;
3884 }
3885
3886 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3887 err_code |= ERR_WARN;
3888
Willy Tarreauef6494c2010-01-28 17:12:36 +01003889 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003890 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3891 file, linenum, args[0]);
3892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
3894 }
3895
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003896 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3897 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3898 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003899 err_code |= ERR_ALERT | ERR_FATAL;
3900 goto out;
3901 }
3902
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003903 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3904 * where force-persist is applied.
3905 */
3906 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003907
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003908 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003909 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003910 if (!strcmp(args[0], "force-persist")) {
3911 rule->type = PERSIST_TYPE_FORCE;
3912 } else {
3913 rule->type = PERSIST_TYPE_IGNORE;
3914 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003915 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003916 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003917 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003918 else if (!strcmp(args[0], "stick-table")) {
3919 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003920 struct proxy *other;
3921
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003922 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003923 if (other) {
3924 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3925 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3926 err_code |= ERR_ALERT | ERR_FATAL;
3927 goto out;
3928 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003929
Emeric Brun32da3c42010-09-23 18:39:19 +02003930 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003931 curproxy->table.type = (unsigned int)-1;
3932 while (*args[myidx]) {
3933 const char *err;
3934
3935 if (strcmp(args[myidx], "size") == 0) {
3936 myidx++;
3937 if (!*(args[myidx])) {
3938 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3939 file, linenum, args[myidx-1]);
3940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
3942 }
3943 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3944 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3945 file, linenum, *err, args[myidx-1]);
3946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
3948 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003949 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003950 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003951 else if (strcmp(args[myidx], "peers") == 0) {
3952 myidx++;
Godbach50523162013-12-11 19:48:57 +08003953 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003954 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3955 file, linenum, args[myidx-1]);
3956 err_code |= ERR_ALERT | ERR_FATAL;
3957 goto out;
Godbach50523162013-12-11 19:48:57 +08003958 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003959 curproxy->table.peers.name = strdup(args[myidx++]);
3960 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003961 else if (strcmp(args[myidx], "expire") == 0) {
3962 myidx++;
3963 if (!*(args[myidx])) {
3964 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3965 file, linenum, args[myidx-1]);
3966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
3968 }
3969 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3970 if (err) {
3971 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3972 file, linenum, *err, args[myidx-1]);
3973 err_code |= ERR_ALERT | ERR_FATAL;
3974 goto out;
3975 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00003976 if (val > INT_MAX) {
3977 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
3978 file, linenum, val);
3979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
3981 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003982 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003983 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003984 }
3985 else if (strcmp(args[myidx], "nopurge") == 0) {
3986 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003987 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003988 }
3989 else if (strcmp(args[myidx], "type") == 0) {
3990 myidx++;
3991 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3992 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3993 file, linenum, args[myidx]);
3994 err_code |= ERR_ALERT | ERR_FATAL;
3995 goto out;
3996 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003997 /* myidx already points to next arg */
3998 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003999 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004000 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004001 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004002
4003 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004004 nw = args[myidx];
4005 while (*nw) {
4006 /* the "store" keyword supports a comma-separated list */
4007 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004008 sa = NULL; /* store arg */
4009 while (*nw && *nw != ',') {
4010 if (*nw == '(') {
4011 *nw = 0;
4012 sa = ++nw;
4013 while (*nw != ')') {
4014 if (!*nw) {
4015 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4016 file, linenum, args[0], cw);
4017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
4019 }
4020 nw++;
4021 }
4022 *nw = '\0';
4023 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004024 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004025 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004026 if (*nw)
4027 *nw++ = '\0';
4028 type = stktable_get_data_type(cw);
4029 if (type < 0) {
4030 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4031 file, linenum, args[0], cw);
4032 err_code |= ERR_ALERT | ERR_FATAL;
4033 goto out;
4034 }
Willy Tarreauac782882010-06-20 10:41:54 +02004035
4036 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4037 switch (err) {
4038 case PE_NONE: break;
4039 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004040 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4041 file, linenum, args[0], cw);
4042 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004043 break;
4044
4045 case PE_ARG_MISSING:
4046 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4047 file, linenum, args[0], cw);
4048 err_code |= ERR_ALERT | ERR_FATAL;
4049 goto out;
4050
4051 case PE_ARG_NOT_USED:
4052 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4053 file, linenum, args[0], cw);
4054 err_code |= ERR_ALERT | ERR_FATAL;
4055 goto out;
4056
4057 default:
4058 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4059 file, linenum, args[0], cw);
4060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004062 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004063 }
4064 myidx++;
4065 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004066 else {
4067 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4068 file, linenum, args[myidx]);
4069 err_code |= ERR_ALERT | ERR_FATAL;
4070 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004071 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004072 }
4073
4074 if (!curproxy->table.size) {
4075 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4076 file, linenum);
4077 err_code |= ERR_ALERT | ERR_FATAL;
4078 goto out;
4079 }
4080
4081 if (curproxy->table.type == (unsigned int)-1) {
4082 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4083 file, linenum);
4084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
4086 }
4087 }
4088 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004089 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004090 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004091 int myidx = 0;
4092 const char *name = NULL;
4093 int flags;
4094
4095 if (curproxy == &defproxy) {
4096 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
4099 }
4100
4101 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4102 err_code |= ERR_WARN;
4103 goto out;
4104 }
4105
4106 myidx++;
4107 if ((strcmp(args[myidx], "store") == 0) ||
4108 (strcmp(args[myidx], "store-request") == 0)) {
4109 myidx++;
4110 flags = STK_IS_STORE;
4111 }
4112 else if (strcmp(args[myidx], "store-response") == 0) {
4113 myidx++;
4114 flags = STK_IS_STORE | STK_ON_RSP;
4115 }
4116 else if (strcmp(args[myidx], "match") == 0) {
4117 myidx++;
4118 flags = STK_IS_MATCH;
4119 }
4120 else if (strcmp(args[myidx], "on") == 0) {
4121 myidx++;
4122 flags = STK_IS_MATCH | STK_IS_STORE;
4123 }
4124 else {
4125 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4126 err_code |= ERR_ALERT | ERR_FATAL;
4127 goto out;
4128 }
4129
4130 if (*(args[myidx]) == 0) {
4131 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4132 err_code |= ERR_ALERT | ERR_FATAL;
4133 goto out;
4134 }
4135
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004136 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004137 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004138 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004139 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
4142 }
4143
4144 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004145 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4146 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4147 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004148 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004149 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004150 goto out;
4151 }
4152 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004153 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4154 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4155 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004156 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004157 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004158 goto out;
4159 }
4160 }
4161
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004162 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004163 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004164
Emeric Brunb982a3d2010-01-04 15:45:53 +01004165 if (strcmp(args[myidx], "table") == 0) {
4166 myidx++;
4167 name = args[myidx++];
4168 }
4169
Willy Tarreauef6494c2010-01-28 17:12:36 +01004170 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004171 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4172 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4173 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004174 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004175 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004176 goto out;
4177 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004178 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004179 else if (*(args[myidx])) {
4180 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4181 file, linenum, args[0], args[myidx]);
4182 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004183 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004184 goto out;
4185 }
Emeric Brun97679e72010-09-23 17:56:44 +02004186 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004187 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004188 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004189 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004190
Emeric Brunb982a3d2010-01-04 15:45:53 +01004191 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4192 rule->cond = cond;
4193 rule->expr = expr;
4194 rule->flags = flags;
4195 rule->table.name = name ? strdup(name) : NULL;
4196 LIST_INIT(&rule->list);
4197 if (flags & STK_ON_RSP)
4198 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4199 else
4200 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4201 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004202 else if (!strcmp(args[0], "stats")) {
4203 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4204 curproxy->uri_auth = NULL; /* we must detach from the default config */
4205
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004206 if (!*args[1]) {
4207 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004208 } else if (!strcmp(args[1], "admin")) {
4209 struct stats_admin_rule *rule;
4210
4211 if (curproxy == &defproxy) {
4212 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4213 err_code |= ERR_ALERT | ERR_FATAL;
4214 goto out;
4215 }
4216
4217 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4218 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4219 err_code |= ERR_ALERT | ERR_ABORT;
4220 goto out;
4221 }
4222
4223 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4224 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4225 file, linenum, args[0], args[1]);
4226 err_code |= ERR_ALERT | ERR_FATAL;
4227 goto out;
4228 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004229 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4230 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4231 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004232 err_code |= ERR_ALERT | ERR_FATAL;
4233 goto out;
4234 }
4235
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004236 err_code |= warnif_cond_conflicts(cond,
4237 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4238 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004239
4240 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4241 rule->cond = cond;
4242 LIST_INIT(&rule->list);
4243 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004244 } else if (!strcmp(args[1], "uri")) {
4245 if (*(args[2]) == 0) {
4246 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004247 err_code |= ERR_ALERT | ERR_FATAL;
4248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004249 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4250 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004251 err_code |= ERR_ALERT | ERR_ABORT;
4252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004253 }
4254 } else if (!strcmp(args[1], "realm")) {
4255 if (*(args[2]) == 0) {
4256 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004259 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4260 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004261 err_code |= ERR_ALERT | ERR_ABORT;
4262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004263 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004264 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004265 unsigned interval;
4266
4267 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4268 if (err) {
4269 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4270 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004271 err_code |= ERR_ALERT | ERR_FATAL;
4272 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004273 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4274 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004275 err_code |= ERR_ALERT | ERR_ABORT;
4276 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004277 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004278 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004279 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004280
4281 if (curproxy == &defproxy) {
4282 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4283 err_code |= ERR_ALERT | ERR_FATAL;
4284 goto out;
4285 }
4286
4287 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4288 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4289 err_code |= ERR_ALERT | ERR_ABORT;
4290 goto out;
4291 }
4292
Willy Tarreauff011f22011-01-06 17:51:27 +01004293 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004294 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004295 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4296 file, linenum, args[0]);
4297 err_code |= ERR_WARN;
4298 }
4299
Willy Tarreauff011f22011-01-06 17:51:27 +01004300 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004301
Willy Tarreauff011f22011-01-06 17:51:27 +01004302 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004303 err_code |= ERR_ALERT | ERR_ABORT;
4304 goto out;
4305 }
4306
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004307 err_code |= warnif_cond_conflicts(rule->cond,
4308 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4309 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004310 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004311
Willy Tarreaubaaee002006-06-26 02:48:02 +02004312 } else if (!strcmp(args[1], "auth")) {
4313 if (*(args[2]) == 0) {
4314 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004317 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4318 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004319 err_code |= ERR_ALERT | ERR_ABORT;
4320 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004321 }
4322 } else if (!strcmp(args[1], "scope")) {
4323 if (*(args[2]) == 0) {
4324 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004325 err_code |= ERR_ALERT | ERR_FATAL;
4326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004327 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4328 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004329 err_code |= ERR_ALERT | ERR_ABORT;
4330 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004331 }
4332 } else if (!strcmp(args[1], "enable")) {
4333 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4334 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004335 err_code |= ERR_ALERT | ERR_ABORT;
4336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004337 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004338 } else if (!strcmp(args[1], "hide-version")) {
4339 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4340 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004341 err_code |= ERR_ALERT | ERR_ABORT;
4342 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004343 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004344 } else if (!strcmp(args[1], "show-legends")) {
4345 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4346 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4347 err_code |= ERR_ALERT | ERR_ABORT;
4348 goto out;
4349 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004350 } else if (!strcmp(args[1], "show-node")) {
4351
4352 if (*args[2]) {
4353 int i;
4354 char c;
4355
4356 for (i=0; args[2][i]; i++) {
4357 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004358 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4359 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004360 break;
4361 }
4362
4363 if (!i || args[2][i]) {
4364 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4365 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4366 file, linenum, args[0], args[1]);
4367 err_code |= ERR_ALERT | ERR_FATAL;
4368 goto out;
4369 }
4370 }
4371
4372 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4373 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4374 err_code |= ERR_ALERT | ERR_ABORT;
4375 goto out;
4376 }
4377 } else if (!strcmp(args[1], "show-desc")) {
4378 char *desc = NULL;
4379
4380 if (*args[2]) {
4381 int i, len=0;
4382 char *d;
4383
Willy Tarreau348acfe2014-04-14 15:00:39 +02004384 for (i = 2; *args[i]; i++)
4385 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004386
4387 desc = d = (char *)calloc(1, len);
4388
Willy Tarreau348acfe2014-04-14 15:00:39 +02004389 d += snprintf(d, desc + len - d, "%s", args[2]);
4390 for (i = 3; *args[i]; i++)
4391 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004392 }
4393
4394 if (!*args[2] && !global.desc)
4395 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4396 file, linenum, args[1]);
4397 else {
4398 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4399 free(desc);
4400 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4401 err_code |= ERR_ALERT | ERR_ABORT;
4402 goto out;
4403 }
4404 free(desc);
4405 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004406 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004407stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004408 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 +01004409 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004410 err_code |= ERR_ALERT | ERR_FATAL;
4411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004412 }
4413 }
4414 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004415 int optnum;
4416
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004417 if (*(args[1]) == '\0') {
4418 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4419 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004420 err_code |= ERR_ALERT | ERR_FATAL;
4421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004422 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004423
4424 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4425 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004426 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4427 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4428 file, linenum, cfg_opts[optnum].name);
4429 err_code |= ERR_ALERT | ERR_FATAL;
4430 goto out;
4431 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004432 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4433 goto out;
4434
Willy Tarreau93893792009-07-23 13:19:11 +02004435 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4436 err_code |= ERR_WARN;
4437 goto out;
4438 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004439
Willy Tarreau3842f002009-06-14 11:39:52 +02004440 curproxy->no_options &= ~cfg_opts[optnum].val;
4441 curproxy->options &= ~cfg_opts[optnum].val;
4442
4443 switch (kwm) {
4444 case KWM_STD:
4445 curproxy->options |= cfg_opts[optnum].val;
4446 break;
4447 case KWM_NO:
4448 curproxy->no_options |= cfg_opts[optnum].val;
4449 break;
4450 case KWM_DEF: /* already cleared */
4451 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004452 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004453
Willy Tarreau93893792009-07-23 13:19:11 +02004454 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004455 }
4456 }
4457
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004458 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4459 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004460 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4461 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4462 file, linenum, cfg_opts2[optnum].name);
4463 err_code |= ERR_ALERT | ERR_FATAL;
4464 goto out;
4465 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004466 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4467 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004468 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4469 err_code |= ERR_WARN;
4470 goto out;
4471 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004472
Willy Tarreau3842f002009-06-14 11:39:52 +02004473 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4474 curproxy->options2 &= ~cfg_opts2[optnum].val;
4475
4476 switch (kwm) {
4477 case KWM_STD:
4478 curproxy->options2 |= cfg_opts2[optnum].val;
4479 break;
4480 case KWM_NO:
4481 curproxy->no_options2 |= cfg_opts2[optnum].val;
4482 break;
4483 case KWM_DEF: /* already cleared */
4484 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004485 }
Willy Tarreau93893792009-07-23 13:19:11 +02004486 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004487 }
4488 }
4489
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004490 /* HTTP options override each other. They can be cancelled using
4491 * "no option xxx" which only switches to default mode if the mode
4492 * was this one (useful for cancelling options set in defaults
4493 * sections).
4494 */
4495 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004496 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4497 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004498 if (kwm == KWM_STD) {
4499 curproxy->options &= ~PR_O_HTTP_MODE;
4500 curproxy->options |= PR_O_HTTP_PCL;
4501 goto out;
4502 }
4503 else if (kwm == KWM_NO) {
4504 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4505 curproxy->options &= ~PR_O_HTTP_MODE;
4506 goto out;
4507 }
4508 }
4509 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004510 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4511 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004512 if (kwm == KWM_STD) {
4513 curproxy->options &= ~PR_O_HTTP_MODE;
4514 curproxy->options |= PR_O_HTTP_FCL;
4515 goto out;
4516 }
4517 else if (kwm == KWM_NO) {
4518 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4519 curproxy->options &= ~PR_O_HTTP_MODE;
4520 goto out;
4521 }
4522 }
4523 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004524 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4525 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004526 if (kwm == KWM_STD) {
4527 curproxy->options &= ~PR_O_HTTP_MODE;
4528 curproxy->options |= PR_O_HTTP_SCL;
4529 goto out;
4530 }
4531 else if (kwm == KWM_NO) {
4532 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4533 curproxy->options &= ~PR_O_HTTP_MODE;
4534 goto out;
4535 }
4536 }
4537 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004538 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4539 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004540 if (kwm == KWM_STD) {
4541 curproxy->options &= ~PR_O_HTTP_MODE;
4542 curproxy->options |= PR_O_HTTP_KAL;
4543 goto out;
4544 }
4545 else if (kwm == KWM_NO) {
4546 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4547 curproxy->options &= ~PR_O_HTTP_MODE;
4548 goto out;
4549 }
4550 }
4551 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004552 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4553 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004554 if (kwm == KWM_STD) {
4555 curproxy->options &= ~PR_O_HTTP_MODE;
4556 curproxy->options |= PR_O_HTTP_TUN;
4557 goto out;
4558 }
4559 else if (kwm == KWM_NO) {
4560 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4561 curproxy->options &= ~PR_O_HTTP_MODE;
4562 goto out;
4563 }
4564 }
4565
Joseph Lynch726ab712015-05-11 23:25:34 -07004566 /* Redispatch can take an integer argument that control when the
4567 * resispatch occurs. All values are relative to the retries option.
4568 * This can be cancelled using "no option xxx".
4569 */
4570 if (strcmp(args[1], "redispatch") == 0) {
4571 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4572 err_code |= ERR_WARN;
4573 goto out;
4574 }
4575
4576 curproxy->no_options &= ~PR_O_REDISP;
4577 curproxy->options &= ~PR_O_REDISP;
4578
4579 switch (kwm) {
4580 case KWM_STD:
4581 curproxy->options |= PR_O_REDISP;
4582 curproxy->redispatch_after = -1;
4583 if(*args[2]) {
4584 curproxy->redispatch_after = atol(args[2]);
4585 }
4586 break;
4587 case KWM_NO:
4588 curproxy->no_options |= PR_O_REDISP;
4589 curproxy->redispatch_after = 0;
4590 break;
4591 case KWM_DEF: /* already cleared */
4592 break;
4593 }
4594 goto out;
4595 }
4596
Willy Tarreau3842f002009-06-14 11:39:52 +02004597 if (kwm != KWM_STD) {
4598 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004599 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004600 err_code |= ERR_ALERT | ERR_FATAL;
4601 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004602 }
4603
Emeric Brun3a058f32009-06-30 18:26:00 +02004604 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004605 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004606 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004607 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004608 if (*(args[2]) != '\0') {
4609 if (!strcmp(args[2], "clf")) {
4610 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004611 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004612 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004613 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004614 err_code |= ERR_ALERT | ERR_FATAL;
4615 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004616 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004617 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4618 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004619 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004620 if (curproxy->conf.logformat_string != default_http_log_format &&
4621 curproxy->conf.logformat_string != default_tcp_log_format &&
4622 curproxy->conf.logformat_string != clf_http_log_format)
4623 free(curproxy->conf.logformat_string);
4624 curproxy->conf.logformat_string = logformat;
4625
4626 free(curproxy->conf.lfs_file);
4627 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4628 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004629 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004630 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004631 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004632 if (curproxy->conf.logformat_string != default_http_log_format &&
4633 curproxy->conf.logformat_string != default_tcp_log_format &&
4634 curproxy->conf.logformat_string != clf_http_log_format)
4635 free(curproxy->conf.logformat_string);
4636 curproxy->conf.logformat_string = default_tcp_log_format;
4637
4638 free(curproxy->conf.lfs_file);
4639 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4640 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004641
4642 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4643 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004644 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004645 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004646 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004647 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004648 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004649
William Lallemanddf1425a2015-04-28 20:17:49 +02004650 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4651 goto out;
4652
Willy Tarreau13943ab2006-12-31 00:24:10 +01004653 if (curproxy->cap & PR_CAP_FE)
4654 curproxy->options |= PR_O_TCP_CLI_KA;
4655 if (curproxy->cap & PR_CAP_BE)
4656 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004657 }
4658 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004659 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004660 err_code |= ERR_WARN;
4661
Willy Tarreaubaaee002006-06-26 02:48:02 +02004662 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004663 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004664 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004665 curproxy->options2 &= ~PR_O2_CHK_ANY;
4666 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004667 if (!*args[2]) { /* no argument */
4668 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4669 curproxy->check_len = strlen(DEF_CHECK_REQ);
4670 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004671 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004672 curproxy->check_req = (char *)malloc(reqlen);
4673 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004674 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004675 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004676 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004677 if (*args[4])
4678 reqlen += strlen(args[4]);
4679 else
4680 reqlen += strlen("HTTP/1.0");
4681
4682 curproxy->check_req = (char *)malloc(reqlen);
4683 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004684 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004685 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004686 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4687 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004688 }
4689 else if (!strcmp(args[1], "ssl-hello-chk")) {
4690 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004691 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004692 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004693
Willy Tarreaua534fea2008-08-03 12:19:50 +02004694 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004695 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004696 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004697 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004698
4699 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004701 }
Willy Tarreau23677902007-05-08 23:50:35 +02004702 else if (!strcmp(args[1], "smtpchk")) {
4703 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004704 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004705 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004706 curproxy->options2 &= ~PR_O2_CHK_ANY;
4707 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004708
4709 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4710 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4711 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4712 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4713 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4714 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4715 curproxy->check_req = (char *)malloc(reqlen);
4716 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4717 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4718 } else {
4719 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4720 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4721 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4722 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4723 }
4724 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004725 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4726 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004727 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004728 else if (!strcmp(args[1], "pgsql-check")) {
4729 /* use PostgreSQL request to check servers' health */
4730 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4731 err_code |= ERR_WARN;
4732
4733 free(curproxy->check_req);
4734 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004735 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004736 curproxy->options2 |= PR_O2_PGSQL_CHK;
4737
4738 if (*(args[2])) {
4739 int cur_arg = 2;
4740
4741 while (*(args[cur_arg])) {
4742 if (strcmp(args[cur_arg], "user") == 0) {
4743 char * packet;
4744 uint32_t packet_len;
4745 uint32_t pv;
4746
4747 /* suboption header - needs additional argument for it */
4748 if (*(args[cur_arg+1]) == 0) {
4749 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4750 file, linenum, args[0], args[1], args[cur_arg]);
4751 err_code |= ERR_ALERT | ERR_FATAL;
4752 goto out;
4753 }
4754
4755 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4756 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4757 pv = htonl(0x30000); /* protocol version 3.0 */
4758
4759 packet = (char*) calloc(1, packet_len);
4760
4761 memcpy(packet + 4, &pv, 4);
4762
4763 /* copy "user" */
4764 memcpy(packet + 8, "user", 4);
4765
4766 /* copy username */
4767 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4768
4769 free(curproxy->check_req);
4770 curproxy->check_req = packet;
4771 curproxy->check_len = packet_len;
4772
4773 packet_len = htonl(packet_len);
4774 memcpy(packet, &packet_len, 4);
4775 cur_arg += 2;
4776 } else {
4777 /* unknown suboption - catchall */
4778 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4779 file, linenum, args[0], args[1]);
4780 err_code |= ERR_ALERT | ERR_FATAL;
4781 goto out;
4782 }
4783 } /* end while loop */
4784 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004785 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4786 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004787 }
4788
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004789 else if (!strcmp(args[1], "redis-check")) {
4790 /* use REDIS PING request to check servers' health */
4791 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4792 err_code |= ERR_WARN;
4793
4794 free(curproxy->check_req);
4795 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004796 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004797 curproxy->options2 |= PR_O2_REDIS_CHK;
4798
4799 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4800 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4801 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004802
4803 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4804 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004805 }
4806
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004807 else if (!strcmp(args[1], "mysql-check")) {
4808 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004809 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4810 err_code |= ERR_WARN;
4811
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004812 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004813 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004814 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004815 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004816
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004817 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004818 * const char mysql40_client_auth_pkt[] = {
4819 * "\x0e\x00\x00" // packet length
4820 * "\x01" // packet number
4821 * "\x00\x00" // client capabilities
4822 * "\x00\x00\x01" // max packet
4823 * "haproxy\x00" // username (null terminated string)
4824 * "\x00" // filler (always 0x00)
4825 * "\x01\x00\x00" // packet length
4826 * "\x00" // packet number
4827 * "\x01" // COM_QUIT command
4828 * };
4829 */
4830
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004831 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4832 * const char mysql41_client_auth_pkt[] = {
4833 * "\x0e\x00\x00\" // packet length
4834 * "\x01" // packet number
4835 * "\x00\x00\x00\x00" // client capabilities
4836 * "\x00\x00\x00\x01" // max packet
4837 * "\x21" // character set (UTF-8)
4838 * char[23] // All zeroes
4839 * "haproxy\x00" // username (null terminated string)
4840 * "\x00" // filler (always 0x00)
4841 * "\x01\x00\x00" // packet length
4842 * "\x00" // packet number
4843 * "\x01" // COM_QUIT command
4844 * };
4845 */
4846
4847
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004848 if (*(args[2])) {
4849 int cur_arg = 2;
4850
4851 while (*(args[cur_arg])) {
4852 if (strcmp(args[cur_arg], "user") == 0) {
4853 char *mysqluser;
4854 int packetlen, reqlen, userlen;
4855
4856 /* suboption header - needs additional argument for it */
4857 if (*(args[cur_arg+1]) == 0) {
4858 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4859 file, linenum, args[0], args[1], args[cur_arg]);
4860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
4862 }
4863 mysqluser = args[cur_arg + 1];
4864 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004865
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004866 if (*(args[cur_arg+2])) {
4867 if (!strcmp(args[cur_arg+2], "post-41")) {
4868 packetlen = userlen + 7 + 27;
4869 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004870
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004871 free(curproxy->check_req);
4872 curproxy->check_req = (char *)calloc(1, reqlen);
4873 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004874
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004875 snprintf(curproxy->check_req, 4, "%c%c%c",
4876 ((unsigned char) packetlen & 0xff),
4877 ((unsigned char) (packetlen >> 8) & 0xff),
4878 ((unsigned char) (packetlen >> 16) & 0xff));
4879
4880 curproxy->check_req[3] = 1;
4881 curproxy->check_req[5] = 130;
4882 curproxy->check_req[11] = 1;
4883 curproxy->check_req[12] = 33;
4884 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4885 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4886 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4887 cur_arg += 3;
4888 } else {
4889 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4890 err_code |= ERR_ALERT | ERR_FATAL;
4891 goto out;
4892 }
4893 } else {
4894 packetlen = userlen + 7;
4895 reqlen = packetlen + 9;
4896
4897 free(curproxy->check_req);
4898 curproxy->check_req = (char *)calloc(1, reqlen);
4899 curproxy->check_len = reqlen;
4900
4901 snprintf(curproxy->check_req, 4, "%c%c%c",
4902 ((unsigned char) packetlen & 0xff),
4903 ((unsigned char) (packetlen >> 8) & 0xff),
4904 ((unsigned char) (packetlen >> 16) & 0xff));
4905
4906 curproxy->check_req[3] = 1;
4907 curproxy->check_req[5] = 128;
4908 curproxy->check_req[8] = 1;
4909 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4910 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4911 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4912 cur_arg += 2;
4913 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004914 } else {
4915 /* unknown suboption - catchall */
4916 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4917 file, linenum, args[0], args[1]);
4918 err_code |= ERR_ALERT | ERR_FATAL;
4919 goto out;
4920 }
4921 } /* end while loop */
4922 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004923 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004924 else if (!strcmp(args[1], "ldap-check")) {
4925 /* use LDAP request to check servers' health */
4926 free(curproxy->check_req);
4927 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004928 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004929 curproxy->options2 |= PR_O2_LDAP_CHK;
4930
4931 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4932 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4933 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004934 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4935 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004936 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004937 else if (!strcmp(args[1], "tcp-check")) {
4938 /* use raw TCPCHK send/expect to check servers' health */
4939 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4940 err_code |= ERR_WARN;
4941
4942 free(curproxy->check_req);
4943 curproxy->check_req = NULL;
4944 curproxy->options2 &= ~PR_O2_CHK_ANY;
4945 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004946 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4947 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004948 }
Simon Horman98637e52014-06-20 12:30:16 +09004949 else if (!strcmp(args[1], "external-check")) {
4950 /* excute an external command to check servers' health */
4951 free(curproxy->check_req);
4952 curproxy->check_req = NULL;
4953 curproxy->options2 &= ~PR_O2_CHK_ANY;
4954 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004955 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4956 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004957 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004958 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004959 int cur_arg;
4960
4961 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4962 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004963 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004964
Willy Tarreau87cf5142011-08-19 22:57:24 +02004965 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004966
4967 free(curproxy->fwdfor_hdr_name);
4968 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4969 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4970
4971 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4972 cur_arg = 2;
4973 while (*(args[cur_arg])) {
4974 if (!strcmp(args[cur_arg], "except")) {
4975 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004976 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004977 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4978 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004979 err_code |= ERR_ALERT | ERR_FATAL;
4980 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004981 }
4982 /* flush useless bits */
4983 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004984 cur_arg += 2;
4985 } else if (!strcmp(args[cur_arg], "header")) {
4986 /* suboption header - needs additional argument for it */
4987 if (*(args[cur_arg+1]) == 0) {
4988 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4989 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004990 err_code |= ERR_ALERT | ERR_FATAL;
4991 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004992 }
4993 free(curproxy->fwdfor_hdr_name);
4994 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4995 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4996 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004997 } else if (!strcmp(args[cur_arg], "if-none")) {
4998 curproxy->options &= ~PR_O_FF_ALWAYS;
4999 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005000 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005001 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005002 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005003 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005004 err_code |= ERR_ALERT | ERR_FATAL;
5005 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005006 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005007 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005008 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005009 else if (!strcmp(args[1], "originalto")) {
5010 int cur_arg;
5011
5012 /* insert x-original-to field, but not for the IP address listed as an except.
5013 * set default options (ie: bitfield, header name, etc)
5014 */
5015
5016 curproxy->options |= PR_O_ORGTO;
5017
5018 free(curproxy->orgto_hdr_name);
5019 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5020 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5021
Willy Tarreau87cf5142011-08-19 22:57:24 +02005022 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005023 cur_arg = 2;
5024 while (*(args[cur_arg])) {
5025 if (!strcmp(args[cur_arg], "except")) {
5026 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005027 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 +02005028 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5029 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005030 err_code |= ERR_ALERT | ERR_FATAL;
5031 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005032 }
5033 /* flush useless bits */
5034 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5035 cur_arg += 2;
5036 } else if (!strcmp(args[cur_arg], "header")) {
5037 /* suboption header - needs additional argument for it */
5038 if (*(args[cur_arg+1]) == 0) {
5039 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5040 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005041 err_code |= ERR_ALERT | ERR_FATAL;
5042 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005043 }
5044 free(curproxy->orgto_hdr_name);
5045 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5046 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5047 cur_arg += 2;
5048 } else {
5049 /* unknown suboption - catchall */
5050 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5051 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005052 err_code |= ERR_ALERT | ERR_FATAL;
5053 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005054 }
5055 } /* end while loop */
5056 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005057 else {
5058 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005061 }
Willy Tarreau93893792009-07-23 13:19:11 +02005062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005063 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005064 else if (!strcmp(args[0], "default_backend")) {
5065 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005066 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005067
5068 if (*(args[1]) == 0) {
5069 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005070 err_code |= ERR_ALERT | ERR_FATAL;
5071 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005072 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005073 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005074 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005075
5076 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5077 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005078 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005079 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005080 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005081 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005082
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005083 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5084 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 +01005085 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005086 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005087 /* enable reconnections to dispatch */
5088 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005089
5090 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005092 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005093 else if (!strcmp(args[0], "http-reuse")) {
5094 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5095 err_code |= ERR_WARN;
5096
5097 if (strcmp(args[1], "never") == 0) {
5098 /* enable a graceful server shutdown on an HTTP 404 response */
5099 curproxy->options &= ~PR_O_REUSE_MASK;
5100 curproxy->options |= PR_O_REUSE_NEVR;
5101 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5102 goto out;
5103 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005104 else if (strcmp(args[1], "safe") == 0) {
5105 /* enable a graceful server shutdown on an HTTP 404 response */
5106 curproxy->options &= ~PR_O_REUSE_MASK;
5107 curproxy->options |= PR_O_REUSE_SAFE;
5108 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5109 goto out;
5110 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005111 else if (strcmp(args[1], "aggressive") == 0) {
5112 curproxy->options &= ~PR_O_REUSE_MASK;
5113 curproxy->options |= PR_O_REUSE_AGGR;
5114 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5115 goto out;
5116 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005117 else if (strcmp(args[1], "always") == 0) {
5118 /* enable a graceful server shutdown on an HTTP 404 response */
5119 curproxy->options &= ~PR_O_REUSE_MASK;
5120 curproxy->options |= PR_O_REUSE_ALWS;
5121 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5122 goto out;
5123 }
5124 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005125 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005126 err_code |= ERR_ALERT | ERR_FATAL;
5127 goto out;
5128 }
5129 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005130 else if (!strcmp(args[0], "http-check")) {
5131 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005132 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005133
5134 if (strcmp(args[1], "disable-on-404") == 0) {
5135 /* enable a graceful server shutdown on an HTTP 404 response */
5136 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005137 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5138 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005139 }
Willy Tarreauef781042010-01-27 11:53:01 +01005140 else if (strcmp(args[1], "send-state") == 0) {
5141 /* enable emission of the apparent state of a server in HTTP checks */
5142 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005143 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5144 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005145 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005146 else if (strcmp(args[1], "expect") == 0) {
5147 const char *ptr_arg;
5148 int cur_arg;
5149
5150 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5151 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5152 err_code |= ERR_ALERT | ERR_FATAL;
5153 goto out;
5154 }
5155
5156 cur_arg = 2;
5157 /* consider exclamation marks, sole or at the beginning of a word */
5158 while (*(ptr_arg = args[cur_arg])) {
5159 while (*ptr_arg == '!') {
5160 curproxy->options2 ^= PR_O2_EXP_INV;
5161 ptr_arg++;
5162 }
5163 if (*ptr_arg)
5164 break;
5165 cur_arg++;
5166 }
5167 /* now ptr_arg points to the beginning of a word past any possible
5168 * exclamation mark, and cur_arg is the argument which holds this word.
5169 */
5170 if (strcmp(ptr_arg, "status") == 0) {
5171 if (!*(args[cur_arg + 1])) {
5172 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5173 file, linenum, args[0], args[1], ptr_arg);
5174 err_code |= ERR_ALERT | ERR_FATAL;
5175 goto out;
5176 }
5177 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005178 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005179 curproxy->expect_str = strdup(args[cur_arg + 1]);
5180 }
5181 else if (strcmp(ptr_arg, "string") == 0) {
5182 if (!*(args[cur_arg + 1])) {
5183 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5184 file, linenum, args[0], args[1], ptr_arg);
5185 err_code |= ERR_ALERT | ERR_FATAL;
5186 goto out;
5187 }
5188 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005189 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005190 curproxy->expect_str = strdup(args[cur_arg + 1]);
5191 }
5192 else if (strcmp(ptr_arg, "rstatus") == 0) {
5193 if (!*(args[cur_arg + 1])) {
5194 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5195 file, linenum, args[0], args[1], ptr_arg);
5196 err_code |= ERR_ALERT | ERR_FATAL;
5197 goto out;
5198 }
5199 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005200 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005201 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005202 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005203 free(curproxy->expect_regex);
5204 curproxy->expect_regex = NULL;
5205 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005206 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005207 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5208 error = NULL;
5209 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5210 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5211 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5212 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005213 err_code |= ERR_ALERT | ERR_FATAL;
5214 goto out;
5215 }
5216 }
5217 else if (strcmp(ptr_arg, "rstring") == 0) {
5218 if (!*(args[cur_arg + 1])) {
5219 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5220 file, linenum, args[0], args[1], ptr_arg);
5221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
5223 }
5224 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005225 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005226 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005227 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005228 free(curproxy->expect_regex);
5229 curproxy->expect_regex = NULL;
5230 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005231 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005232 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5233 error = NULL;
5234 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5235 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5236 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5237 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005238 err_code |= ERR_ALERT | ERR_FATAL;
5239 goto out;
5240 }
5241 }
5242 else {
5243 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5244 file, linenum, args[0], args[1], ptr_arg);
5245 err_code |= ERR_ALERT | ERR_FATAL;
5246 goto out;
5247 }
5248 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005249 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005250 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 +02005251 err_code |= ERR_ALERT | ERR_FATAL;
5252 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005253 }
5254 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005255 else if (!strcmp(args[0], "tcp-check")) {
5256 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5257 err_code |= ERR_WARN;
5258
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005259 if (strcmp(args[1], "comment") == 0) {
5260 int cur_arg;
5261 struct tcpcheck_rule *tcpcheck;
5262
5263 cur_arg = 1;
5264 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5265 tcpcheck->action = TCPCHK_ACT_COMMENT;
5266
5267 if (!*args[cur_arg + 1]) {
5268 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5269 file, linenum, args[cur_arg]);
5270 err_code |= ERR_ALERT | ERR_FATAL;
5271 goto out;
5272 }
5273
5274 tcpcheck->comment = strdup(args[cur_arg + 1]);
5275
5276 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005277 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5278 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005279 }
5280 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005281 const char *ptr_arg;
5282 int cur_arg;
5283 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005284
5285 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005286 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5287 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5288 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5289 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5290 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005291
Willy Tarreau5581c272015-05-13 12:24:53 +02005292 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5293 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5294 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5295 file, linenum);
5296 err_code |= ERR_ALERT | ERR_FATAL;
5297 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005298 }
5299
5300 cur_arg = 2;
5301 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5302 tcpcheck->action = TCPCHK_ACT_CONNECT;
5303
5304 /* parsing each parameters to fill up the rule */
5305 while (*(ptr_arg = args[cur_arg])) {
5306 /* tcp port */
5307 if (strcmp(args[cur_arg], "port") == 0) {
5308 if ( (atol(args[cur_arg + 1]) > 65535) ||
5309 (atol(args[cur_arg + 1]) < 1) ){
5310 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5311 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5312 err_code |= ERR_ALERT | ERR_FATAL;
5313 goto out;
5314 }
5315 tcpcheck->port = atol(args[cur_arg + 1]);
5316 cur_arg += 2;
5317 }
5318 /* send proxy protocol */
5319 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5320 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5321 cur_arg++;
5322 }
5323#ifdef USE_OPENSSL
5324 else if (strcmp(args[cur_arg], "ssl") == 0) {
5325 curproxy->options |= PR_O_TCPCHK_SSL;
5326 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5327 cur_arg++;
5328 }
5329#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005330 /* comment for this tcpcheck line */
5331 else if (strcmp(args[cur_arg], "comment") == 0) {
5332 if (!*args[cur_arg + 1]) {
5333 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5334 file, linenum, args[cur_arg]);
5335 err_code |= ERR_ALERT | ERR_FATAL;
5336 goto out;
5337 }
5338 tcpcheck->comment = strdup(args[cur_arg + 1]);
5339 cur_arg += 2;
5340 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005341 else {
5342#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005343 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 +01005344#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005345 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 +01005346#endif /* USE_OPENSSL */
5347 file, linenum, args[0], args[1], args[cur_arg]);
5348 err_code |= ERR_ALERT | ERR_FATAL;
5349 goto out;
5350 }
5351
5352 }
5353
5354 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5355 }
5356 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005357 if (! *(args[2]) ) {
5358 /* SEND string expected */
5359 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5360 file, linenum, args[0], args[1], args[2]);
5361 err_code |= ERR_ALERT | ERR_FATAL;
5362 goto out;
5363 } else {
5364 struct tcpcheck_rule *tcpcheck;
5365
5366 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5367
5368 tcpcheck->action = TCPCHK_ACT_SEND;
5369 tcpcheck->string_len = strlen(args[2]);
5370 tcpcheck->string = strdup(args[2]);
5371 tcpcheck->expect_regex = NULL;
5372
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005373 /* comment for this tcpcheck line */
5374 if (strcmp(args[3], "comment") == 0) {
5375 if (!*args[4]) {
5376 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5377 file, linenum, args[3]);
5378 err_code |= ERR_ALERT | ERR_FATAL;
5379 goto out;
5380 }
5381 tcpcheck->comment = strdup(args[4]);
5382 }
5383
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005384 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5385 }
5386 }
5387 else if (strcmp(args[1], "send-binary") == 0) {
5388 if (! *(args[2]) ) {
5389 /* SEND binary string expected */
5390 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5391 file, linenum, args[0], args[1], args[2]);
5392 err_code |= ERR_ALERT | ERR_FATAL;
5393 goto out;
5394 } else {
5395 struct tcpcheck_rule *tcpcheck;
5396 char *err = NULL;
5397
5398 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5399
5400 tcpcheck->action = TCPCHK_ACT_SEND;
5401 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5402 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5403 file, linenum, args[0], args[1], args[2], err);
5404 err_code |= ERR_ALERT | ERR_FATAL;
5405 goto out;
5406 }
5407 tcpcheck->expect_regex = NULL;
5408
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005409 /* comment for this tcpcheck line */
5410 if (strcmp(args[3], "comment") == 0) {
5411 if (!*args[4]) {
5412 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5413 file, linenum, args[3]);
5414 err_code |= ERR_ALERT | ERR_FATAL;
5415 goto out;
5416 }
5417 tcpcheck->comment = strdup(args[4]);
5418 }
5419
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005420 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5421 }
5422 }
5423 else if (strcmp(args[1], "expect") == 0) {
5424 const char *ptr_arg;
5425 int cur_arg;
5426 int inverse = 0;
5427
5428 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5429 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5430 err_code |= ERR_ALERT | ERR_FATAL;
5431 goto out;
5432 }
5433
5434 cur_arg = 2;
5435 /* consider exclamation marks, sole or at the beginning of a word */
5436 while (*(ptr_arg = args[cur_arg])) {
5437 while (*ptr_arg == '!') {
5438 inverse = !inverse;
5439 ptr_arg++;
5440 }
5441 if (*ptr_arg)
5442 break;
5443 cur_arg++;
5444 }
5445 /* now ptr_arg points to the beginning of a word past any possible
5446 * exclamation mark, and cur_arg is the argument which holds this word.
5447 */
5448 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005449 struct tcpcheck_rule *tcpcheck;
5450 char *err = NULL;
5451
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005452 if (!*(args[cur_arg + 1])) {
5453 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5454 file, linenum, args[0], args[1], ptr_arg);
5455 err_code |= ERR_ALERT | ERR_FATAL;
5456 goto out;
5457 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005458
5459 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5460
5461 tcpcheck->action = TCPCHK_ACT_EXPECT;
5462 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5463 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5464 file, linenum, args[0], args[1], args[2], err);
5465 err_code |= ERR_ALERT | ERR_FATAL;
5466 goto out;
5467 }
5468 tcpcheck->expect_regex = NULL;
5469 tcpcheck->inverse = inverse;
5470
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005471 /* tcpcheck comment */
5472 cur_arg += 2;
5473 if (strcmp(args[cur_arg], "comment") == 0) {
5474 if (!*args[cur_arg + 1]) {
5475 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5476 file, linenum, args[cur_arg + 1]);
5477 err_code |= ERR_ALERT | ERR_FATAL;
5478 goto out;
5479 }
5480 tcpcheck->comment = strdup(args[cur_arg + 1]);
5481 }
5482
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005483 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5484 }
5485 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005486 struct tcpcheck_rule *tcpcheck;
5487
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005488 if (!*(args[cur_arg + 1])) {
5489 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5490 file, linenum, args[0], args[1], ptr_arg);
5491 err_code |= ERR_ALERT | ERR_FATAL;
5492 goto out;
5493 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005494
5495 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5496
5497 tcpcheck->action = TCPCHK_ACT_EXPECT;
5498 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5499 tcpcheck->string = strdup(args[cur_arg + 1]);
5500 tcpcheck->expect_regex = NULL;
5501 tcpcheck->inverse = inverse;
5502
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005503 /* tcpcheck comment */
5504 cur_arg += 2;
5505 if (strcmp(args[cur_arg], "comment") == 0) {
5506 if (!*args[cur_arg + 1]) {
5507 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5508 file, linenum, args[cur_arg + 1]);
5509 err_code |= ERR_ALERT | ERR_FATAL;
5510 goto out;
5511 }
5512 tcpcheck->comment = strdup(args[cur_arg + 1]);
5513 }
5514
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005515 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5516 }
5517 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005518 struct tcpcheck_rule *tcpcheck;
5519
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005520 if (!*(args[cur_arg + 1])) {
5521 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5522 file, linenum, args[0], args[1], ptr_arg);
5523 err_code |= ERR_ALERT | ERR_FATAL;
5524 goto out;
5525 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005526
5527 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5528
5529 tcpcheck->action = TCPCHK_ACT_EXPECT;
5530 tcpcheck->string_len = 0;
5531 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005532 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5533 error = NULL;
5534 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5535 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5536 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5537 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005538 err_code |= ERR_ALERT | ERR_FATAL;
5539 goto out;
5540 }
5541 tcpcheck->inverse = inverse;
5542
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005543 /* tcpcheck comment */
5544 cur_arg += 2;
5545 if (strcmp(args[cur_arg], "comment") == 0) {
5546 if (!*args[cur_arg + 1]) {
5547 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5548 file, linenum, args[cur_arg + 1]);
5549 err_code |= ERR_ALERT | ERR_FATAL;
5550 goto out;
5551 }
5552 tcpcheck->comment = strdup(args[cur_arg + 1]);
5553 }
5554
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005555 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5556 }
5557 else {
5558 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5559 file, linenum, args[0], args[1], ptr_arg);
5560 err_code |= ERR_ALERT | ERR_FATAL;
5561 goto out;
5562 }
5563 }
5564 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005565 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005566 err_code |= ERR_ALERT | ERR_FATAL;
5567 goto out;
5568 }
5569 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005570 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005571 if (curproxy == &defproxy) {
5572 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005573 err_code |= ERR_ALERT | ERR_FATAL;
5574 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005575 }
5576
Willy Tarreaub80c2302007-11-30 20:51:32 +01005577 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005578 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005579
5580 if (strcmp(args[1], "fail") == 0) {
5581 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005582 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005583 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5584 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005585 err_code |= ERR_ALERT | ERR_FATAL;
5586 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005587 }
5588
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005589 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5590 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5591 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005592 err_code |= ERR_ALERT | ERR_FATAL;
5593 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005594 }
5595 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5596 }
5597 else {
5598 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005599 err_code |= ERR_ALERT | ERR_FATAL;
5600 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005601 }
5602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005603#ifdef TPROXY
5604 else if (!strcmp(args[0], "transparent")) {
5605 /* enable transparent proxy connections */
5606 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005607 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005609 }
5610#endif
5611 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005612 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005613 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005614
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615 if (*(args[1]) == 0) {
5616 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005617 err_code |= ERR_ALERT | ERR_FATAL;
5618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005619 }
5620 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005621 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005623 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005624 else if (!strcmp(args[0], "backlog")) { /* backlog */
5625 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005626 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005627
5628 if (*(args[1]) == 0) {
5629 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005630 err_code |= ERR_ALERT | ERR_FATAL;
5631 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005632 }
5633 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005634 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5635 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005636 }
Willy Tarreau86034312006-12-29 00:10:33 +01005637 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005638 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005639 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005640
Willy Tarreau86034312006-12-29 00:10:33 +01005641 if (*(args[1]) == 0) {
5642 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005643 err_code |= ERR_ALERT | ERR_FATAL;
5644 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005645 }
5646 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005647 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5648 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005650 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5651 if (*(args[1]) == 0) {
5652 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005653 err_code |= ERR_ALERT | ERR_FATAL;
5654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005655 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005656 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5657 if (err) {
5658 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5659 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005660 err_code |= ERR_ALERT | ERR_FATAL;
5661 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005662 }
5663 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005664 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005666 }
5667 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005668 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005669 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005670 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005671
Willy Tarreaubaaee002006-06-26 02:48:02 +02005672 if (curproxy == &defproxy) {
5673 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005674 err_code |= ERR_ALERT | ERR_FATAL;
5675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005676 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005677 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005678 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005679
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005680 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005681 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005682 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005683 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005684 goto out;
5685 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005686
5687 proto = protocol_by_family(sk->ss_family);
5688 if (!proto || !proto->connect) {
5689 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5690 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005691 err_code |= ERR_ALERT | ERR_FATAL;
5692 goto out;
5693 }
5694
5695 if (port1 != port2) {
5696 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5697 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005698 err_code |= ERR_ALERT | ERR_FATAL;
5699 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005700 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005701
5702 if (!port1) {
5703 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5704 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005705 err_code |= ERR_ALERT | ERR_FATAL;
5706 goto out;
5707 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005708
William Lallemanddf1425a2015-04-28 20:17:49 +02005709 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5710 goto out;
5711
Willy Tarreaud5191e72010-02-09 20:50:45 +01005712 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005713 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005714 }
5715 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005716 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005717 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005718
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005719 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5720 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005721 err_code |= ERR_ALERT | ERR_FATAL;
5722 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005723 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005725 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005726 /**
5727 * The syntax for hash-type config element is
5728 * hash-type {map-based|consistent} [[<algo>] avalanche]
5729 *
5730 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5731 */
5732 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005733
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005734 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5735 err_code |= ERR_WARN;
5736
5737 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005738 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5739 }
5740 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005741 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5742 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005743 else if (strcmp(args[1], "avalanche") == 0) {
5744 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]);
5745 err_code |= ERR_ALERT | ERR_FATAL;
5746 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005747 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005748 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005749 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005750 err_code |= ERR_ALERT | ERR_FATAL;
5751 goto out;
5752 }
Bhaskar98634f02013-10-29 23:30:51 -04005753
5754 /* set the hash function to use */
5755 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005756 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005757 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005758
5759 /* if consistent with no argument, then avalanche modifier is also applied */
5760 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5761 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005762 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005763 /* set the hash function */
5764 if (!strcmp(args[2], "sdbm")) {
5765 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5766 }
5767 else if (!strcmp(args[2], "djb2")) {
5768 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005769 }
5770 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005771 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005772 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005773 else if (!strcmp(args[2], "crc32")) {
5774 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5775 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005776 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005777 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 -05005778 err_code |= ERR_ALERT | ERR_FATAL;
5779 goto out;
5780 }
5781
5782 /* set the hash modifier */
5783 if (!strcmp(args[3], "avalanche")) {
5784 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5785 }
5786 else if (*args[3]) {
5787 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5788 err_code |= ERR_ALERT | ERR_FATAL;
5789 goto out;
5790 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005791 }
William Lallemanda73203e2012-03-12 12:48:57 +01005792 }
William Lallemanda73203e2012-03-12 12:48:57 +01005793 else if (strcmp(args[0], "unique-id-format") == 0) {
5794 if (!*(args[1])) {
5795 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5796 err_code |= ERR_ALERT | ERR_FATAL;
5797 goto out;
5798 }
William Lallemand3203ff42012-11-11 17:30:56 +01005799 if (*(args[2])) {
5800 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5801 err_code |= ERR_ALERT | ERR_FATAL;
5802 goto out;
5803 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005804 free(curproxy->conf.uniqueid_format_string);
5805 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005806
Willy Tarreau62a61232013-04-12 18:13:46 +02005807 free(curproxy->conf.uif_file);
5808 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5809 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005810 }
William Lallemanda73203e2012-03-12 12:48:57 +01005811
5812 else if (strcmp(args[0], "unique-id-header") == 0) {
5813 if (!*(args[1])) {
5814 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5815 err_code |= ERR_ALERT | ERR_FATAL;
5816 goto out;
5817 }
5818 free(curproxy->header_unique_id);
5819 curproxy->header_unique_id = strdup(args[1]);
5820 }
5821
William Lallemand723b73a2012-02-08 16:37:49 +01005822 else if (strcmp(args[0], "log-format") == 0) {
5823 if (!*(args[1])) {
5824 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5825 err_code |= ERR_ALERT | ERR_FATAL;
5826 goto out;
5827 }
William Lallemand3203ff42012-11-11 17:30:56 +01005828 if (*(args[2])) {
5829 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5830 err_code |= ERR_ALERT | ERR_FATAL;
5831 goto out;
5832 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005833
Willy Tarreau62a61232013-04-12 18:13:46 +02005834 if (curproxy->conf.logformat_string != default_http_log_format &&
5835 curproxy->conf.logformat_string != default_tcp_log_format &&
5836 curproxy->conf.logformat_string != clf_http_log_format)
5837 free(curproxy->conf.logformat_string);
5838 curproxy->conf.logformat_string = strdup(args[1]);
5839
5840 free(curproxy->conf.lfs_file);
5841 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5842 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005843
5844 /* get a chance to improve log-format error reporting by
5845 * reporting the correct line-number when possible.
5846 */
5847 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5848 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5849 file, linenum, curproxy->id);
5850 err_code |= ERR_WARN;
5851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005852 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005853 else if (!strcmp(args[0], "log-format-sd")) {
5854 if (!*(args[1])) {
5855 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5856 err_code |= ERR_ALERT | ERR_FATAL;
5857 goto out;
5858 }
5859 if (*(args[2])) {
5860 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5861 err_code |= ERR_ALERT | ERR_FATAL;
5862 goto out;
5863 }
5864
5865 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5866 free(curproxy->conf.logformat_sd_string);
5867 curproxy->conf.logformat_sd_string = strdup(args[1]);
5868
5869 free(curproxy->conf.lfsd_file);
5870 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5871 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5872
5873 /* get a chance to improve log-format-sd error reporting by
5874 * reporting the correct line-number when possible.
5875 */
5876 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5877 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5878 file, linenum, curproxy->id);
5879 err_code |= ERR_WARN;
5880 }
5881 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005882 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5883 if (*(args[1]) == 0) {
5884 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5885 err_code |= ERR_ALERT | ERR_FATAL;
5886 goto out;
5887 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005888 chunk_destroy(&curproxy->log_tag);
5889 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005890 }
William Lallemand0f99e342011-10-12 17:50:54 +02005891 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5892 /* delete previous herited or defined syslog servers */
5893 struct logsrv *back;
5894
5895 if (*(args[1]) != 0) {
5896 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5897 err_code |= ERR_ALERT | ERR_FATAL;
5898 goto out;
5899 }
5900
William Lallemand723b73a2012-02-08 16:37:49 +01005901 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5902 LIST_DEL(&tmplogsrv->list);
5903 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005904 }
5905 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005906 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005907 struct logsrv *logsrv;
5908
Willy Tarreaubaaee002006-06-26 02:48:02 +02005909 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005910 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005911 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005912 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005913 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005914 LIST_INIT(&node->list);
5915 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5916 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005917 }
5918 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005919 struct sockaddr_storage *sk;
5920 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005921 int arg = 0;
5922 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005923
5924 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005925
Willy Tarreau18324f52014-06-27 18:10:07 +02005926 /* just after the address, a length may be specified */
5927 if (strcmp(args[arg+2], "len") == 0) {
5928 len = atoi(args[arg+3]);
5929 if (len < 80 || len > 65535) {
5930 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5931 file, linenum, args[arg+3]);
5932 err_code |= ERR_ALERT | ERR_FATAL;
5933 goto out;
5934 }
5935 logsrv->maxlen = len;
5936
5937 /* skip these two args */
5938 arg += 2;
5939 }
5940 else
5941 logsrv->maxlen = MAX_SYSLOG_LEN;
5942
5943 if (logsrv->maxlen > global.max_syslog_len) {
5944 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02005945 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02005946 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005947 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005948 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02005949 }
5950
Dragan Dosen1322d092015-09-22 16:05:32 +02005951 /* after the length, a format may be specified */
5952 if (strcmp(args[arg+2], "format") == 0) {
5953 logsrv->format = get_log_format(args[arg+3]);
5954 if (logsrv->format < 0) {
5955 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
5956 err_code |= ERR_ALERT | ERR_FATAL;
5957 goto out;
5958 }
5959
5960 /* skip these two args */
5961 arg += 2;
5962 }
5963
William Lallemanddf1425a2015-04-28 20:17:49 +02005964 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5965 goto out;
5966
Willy Tarreau18324f52014-06-27 18:10:07 +02005967 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005968 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005969 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005970 err_code |= ERR_ALERT | ERR_FATAL;
5971 goto out;
5972
Willy Tarreaubaaee002006-06-26 02:48:02 +02005973 }
5974
William Lallemand0f99e342011-10-12 17:50:54 +02005975 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005976 if (*(args[arg+3])) {
5977 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005978 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005979 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005980 err_code |= ERR_ALERT | ERR_FATAL;
5981 goto out;
5982
Willy Tarreaubaaee002006-06-26 02:48:02 +02005983 }
5984 }
5985
William Lallemand0f99e342011-10-12 17:50:54 +02005986 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005987 if (*(args[arg+4])) {
5988 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005989 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005990 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005991 err_code |= ERR_ALERT | ERR_FATAL;
5992 goto out;
5993
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005994 }
5995 }
5996
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005997 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005998 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005999 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006000 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006001 goto out;
6002 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006003
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006004 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006005
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006006 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006007 if (port1 != port2) {
6008 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6009 file, linenum, args[0], args[1]);
6010 err_code |= ERR_ALERT | ERR_FATAL;
6011 goto out;
6012 }
6013
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006014 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006015 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006016 }
William Lallemand0f99e342011-10-12 17:50:54 +02006017
6018 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006019 }
6020 else {
6021 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6022 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006023 err_code |= ERR_ALERT | ERR_FATAL;
6024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006025 }
6026 }
6027 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006028 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006029 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006030 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006031 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006032
Willy Tarreau977b8e42006-12-29 14:19:17 +01006033 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006034 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006035
Willy Tarreaubaaee002006-06-26 02:48:02 +02006036 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006037 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6038 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006039 err_code |= ERR_ALERT | ERR_FATAL;
6040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006041 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006042
6043 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006044 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6045 free(curproxy->conn_src.iface_name);
6046 curproxy->conn_src.iface_name = NULL;
6047 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006048
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006049 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006050 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006051 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006052 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006053 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006054 goto out;
6055 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006056
6057 proto = protocol_by_family(sk->ss_family);
6058 if (!proto || !proto->connect) {
6059 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006060 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006061 err_code |= ERR_ALERT | ERR_FATAL;
6062 goto out;
6063 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006064
6065 if (port1 != port2) {
6066 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6067 file, linenum, args[0], args[1]);
6068 err_code |= ERR_ALERT | ERR_FATAL;
6069 goto out;
6070 }
6071
Willy Tarreauef9a3602012-12-08 22:29:20 +01006072 curproxy->conn_src.source_addr = *sk;
6073 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006074
6075 cur_arg = 2;
6076 while (*(args[cur_arg])) {
6077 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006078#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006079 if (!*args[cur_arg + 1]) {
6080 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6081 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006082 err_code |= ERR_ALERT | ERR_FATAL;
6083 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006084 }
6085
6086 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006087 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6088 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006089 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006090 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6091 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006092 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6093 char *name, *end;
6094
6095 name = args[cur_arg+1] + 7;
6096 while (isspace(*name))
6097 name++;
6098
6099 end = name;
6100 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6101 end++;
6102
Willy Tarreauef9a3602012-12-08 22:29:20 +01006103 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6104 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6105 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6106 curproxy->conn_src.bind_hdr_len = end - name;
6107 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6108 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6109 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006110
6111 /* now look for an occurrence number */
6112 while (isspace(*end))
6113 end++;
6114 if (*end == ',') {
6115 end++;
6116 name = end;
6117 if (*end == '-')
6118 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006119 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006120 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006121 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006122 }
6123
Willy Tarreauef9a3602012-12-08 22:29:20 +01006124 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006125 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6126 " occurrences values smaller than %d.\n",
6127 file, linenum, MAX_HDR_HISTORY);
6128 err_code |= ERR_ALERT | ERR_FATAL;
6129 goto out;
6130 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006131 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006132 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006133
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006134 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006135 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006136 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006137 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006138 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006139 goto out;
6140 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006141
6142 proto = protocol_by_family(sk->ss_family);
6143 if (!proto || !proto->connect) {
6144 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6145 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006146 err_code |= ERR_ALERT | ERR_FATAL;
6147 goto out;
6148 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006149
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006150 if (port1 != port2) {
6151 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6152 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006153 err_code |= ERR_ALERT | ERR_FATAL;
6154 goto out;
6155 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006156 curproxy->conn_src.tproxy_addr = *sk;
6157 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006158 }
6159 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006160#else /* no TPROXY support */
6161 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006162 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006163 err_code |= ERR_ALERT | ERR_FATAL;
6164 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006165#endif
6166 cur_arg += 2;
6167 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006168 }
6169
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006170 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6171#ifdef SO_BINDTODEVICE
6172 if (!*args[cur_arg + 1]) {
6173 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6174 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006175 err_code |= ERR_ALERT | ERR_FATAL;
6176 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006177 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006178 free(curproxy->conn_src.iface_name);
6179 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6180 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006181 global.last_checks |= LSTCHK_NETADM;
6182#else
6183 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6184 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006185 err_code |= ERR_ALERT | ERR_FATAL;
6186 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006187#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006188 cur_arg += 2;
6189 continue;
6190 }
6191 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006192 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006193 err_code |= ERR_ALERT | ERR_FATAL;
6194 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006196 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006197 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6198 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6199 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006200 err_code |= ERR_ALERT | ERR_FATAL;
6201 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006202 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006203 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006204 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006205 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6206 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006207 err_code |= ERR_ALERT | ERR_FATAL;
6208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006209 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006210
6211 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006212 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006213 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006214 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006216 }
6217 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006218 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006219 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006220 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006221 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006222 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006223 }
6224 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006225 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006226 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006227 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006228 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006230 }
6231 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006232 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006233 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006234 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006235 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006237 }
6238 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006239 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006240 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006241 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006242 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006244 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006245 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006246 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006247 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006248 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006249 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006250 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006252 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006253 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006254 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6255 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006256 err_code |= ERR_ALERT | ERR_FATAL;
6257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006258 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006259
6260 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006261 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006262 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006263 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006265 }
6266 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006267 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006268 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006269 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006270 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006272 }
6273 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006274 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006275 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006276 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006277 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006279 }
6280 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006281 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006282 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006283 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006284 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006286 }
6287 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006288 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006289 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006290 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006291 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006293 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006294 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006295 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006296 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006297 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006298 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006299 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006300 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006301 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006302 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006303
Willy Tarreaubaaee002006-06-26 02:48:02 +02006304 if (curproxy == &defproxy) {
6305 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006306 err_code |= ERR_ALERT | ERR_FATAL;
6307 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006308 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006309 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006310 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006311
Willy Tarreaubaaee002006-06-26 02:48:02 +02006312 if (*(args[1]) == 0) {
6313 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006314 err_code |= ERR_ALERT | ERR_FATAL;
6315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006316 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006317
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006318 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006319 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6320 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6321 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006322 err_code |= ERR_ALERT | ERR_FATAL;
6323 goto out;
6324 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006325 err_code |= warnif_cond_conflicts(cond,
6326 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6327 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006328 }
6329 else if (*args[2]) {
6330 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6331 file, linenum, args[0], args[2]);
6332 err_code |= ERR_ALERT | ERR_FATAL;
6333 goto out;
6334 }
6335
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006336 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006337 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006338 wl->s = strdup(args[1]);
6339 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006340 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006341 }
6342 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006343 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006344 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6345 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006346 err_code |= ERR_ALERT | ERR_FATAL;
6347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006348 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006349
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_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006352 args[0], args[1], args[2], (const char **)args+3);
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], "rspdel")) { /* delete response header from a regex */
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_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +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], "rspdeny")) { /* block response header from a 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_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +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 }
6370 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006371 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006372 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6373 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006374 err_code |= ERR_ALERT | ERR_FATAL;
6375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006376 }
6377
Willy Tarreauade5ec42010-01-28 19:33:49 +01006378 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006379 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006380 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006381 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006383 }
6384 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006385 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006386 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006387 args[0], args[1], NULL, (const char **)args+2);
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], "rspideny")) { /* block response 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_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +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], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006399 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006400
Willy Tarreaubaaee002006-06-26 02:48:02 +02006401 if (curproxy == &defproxy) {
6402 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006403 err_code |= ERR_ALERT | ERR_FATAL;
6404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006405 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006406 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006407 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006408
Willy Tarreaubaaee002006-06-26 02:48:02 +02006409 if (*(args[1]) == 0) {
6410 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006411 err_code |= ERR_ALERT | ERR_FATAL;
6412 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006413 }
6414
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006415 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006416 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6417 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6418 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006419 err_code |= ERR_ALERT | ERR_FATAL;
6420 goto out;
6421 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006422 err_code |= warnif_cond_conflicts(cond,
6423 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6424 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006425 }
6426 else if (*args[2]) {
6427 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6428 file, linenum, args[0], args[2]);
6429 err_code |= ERR_ALERT | ERR_FATAL;
6430 goto out;
6431 }
6432
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006433 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006434 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006435 wl->s = strdup(args[1]);
6436 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006437 }
6438 else if (!strcmp(args[0], "errorloc") ||
6439 !strcmp(args[0], "errorloc302") ||
6440 !strcmp(args[0], "errorloc303")) { /* error location */
6441 int errnum, errlen;
6442 char *err;
6443
Willy Tarreau977b8e42006-12-29 14:19:17 +01006444 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006445 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006446
Willy Tarreaubaaee002006-06-26 02:48:02 +02006447 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006448 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006449 err_code |= ERR_ALERT | ERR_FATAL;
6450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006451 }
6452
6453 errnum = atol(args[1]);
6454 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006455 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6456 err = malloc(errlen);
6457 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006458 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006459 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6460 err = malloc(errlen);
6461 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006462 }
6463
Willy Tarreau0f772532006-12-23 20:51:41 +01006464 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6465 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006466 chunk_destroy(&curproxy->errmsg[rc]);
6467 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006468 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006470 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006471
6472 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006473 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6474 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006475 free(err);
6476 }
6477 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006478 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6479 int errnum, errlen, fd;
6480 char *err;
6481 struct stat stat;
6482
6483 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006484 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006485
6486 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006487 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006488 err_code |= ERR_ALERT | ERR_FATAL;
6489 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006490 }
6491
6492 fd = open(args[2], O_RDONLY);
6493 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6494 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6495 file, linenum, args[2], args[1]);
6496 if (fd >= 0)
6497 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006498 err_code |= ERR_ALERT | ERR_FATAL;
6499 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006500 }
6501
Willy Tarreau27a674e2009-08-17 07:23:33 +02006502 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006503 errlen = stat.st_size;
6504 } else {
6505 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006506 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006507 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006508 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006509 }
6510
6511 err = malloc(errlen); /* malloc() must succeed during parsing */
6512 errnum = read(fd, err, errlen);
6513 if (errnum != errlen) {
6514 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6515 file, linenum, args[2], args[1]);
6516 close(fd);
6517 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006518 err_code |= ERR_ALERT | ERR_FATAL;
6519 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006520 }
6521 close(fd);
6522
6523 errnum = atol(args[1]);
6524 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6525 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006526 chunk_destroy(&curproxy->errmsg[rc]);
6527 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006528 break;
6529 }
6530 }
6531
6532 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006533 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6534 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006535 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006536 free(err);
6537 }
6538 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006539 else if (!strcmp(args[0], "compression")) {
6540 struct comp *comp;
6541 if (curproxy->comp == NULL) {
6542 comp = calloc(1, sizeof(struct comp));
6543 curproxy->comp = comp;
6544 } else {
6545 comp = curproxy->comp;
6546 }
6547
6548 if (!strcmp(args[1], "algo")) {
6549 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006550 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006551
William Lallemand82fe75c2012-10-23 10:25:10 +02006552 cur_arg = 2;
6553 if (!*args[cur_arg]) {
6554 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6555 file, linenum, args[0]);
6556 err_code |= ERR_ALERT | ERR_FATAL;
6557 goto out;
6558 }
6559 while (*(args[cur_arg])) {
6560 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6561 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6562 file, linenum, args[0], args[cur_arg]);
6563 err_code |= ERR_ALERT | ERR_FATAL;
6564 goto out;
6565 }
William Lallemand552df672012-11-07 13:21:47 +01006566 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6567 curproxy->comp->algos->end(&ctx);
6568 } else {
6569 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6570 file, linenum, args[0], args[cur_arg]);
6571 err_code |= ERR_ALERT | ERR_FATAL;
6572 goto out;
6573 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006574 cur_arg ++;
6575 continue;
6576 }
6577 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006578 else if (!strcmp(args[1], "offload")) {
6579 comp->offload = 1;
6580 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006581 else if (!strcmp(args[1], "type")) {
6582 int cur_arg;
6583 cur_arg = 2;
6584 if (!*args[cur_arg]) {
6585 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6586 file, linenum, args[0]);
6587 err_code |= ERR_ALERT | ERR_FATAL;
6588 goto out;
6589 }
6590 while (*(args[cur_arg])) {
6591 comp_append_type(comp, args[cur_arg]);
6592 cur_arg ++;
6593 continue;
6594 }
6595 }
6596 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006597 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006598 file, linenum, args[0]);
6599 err_code |= ERR_ALERT | ERR_FATAL;
6600 goto out;
6601 }
6602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006603 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006604 struct cfg_kw_list *kwl;
6605 int index;
6606
6607 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6608 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6609 if (kwl->kw[index].section != CFG_LISTEN)
6610 continue;
6611 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6612 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006613 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006614 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006615 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006616 err_code |= ERR_ALERT | ERR_FATAL;
6617 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006618 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006619 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006620 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006621 err_code |= ERR_WARN;
6622 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006623 }
Willy Tarreau93893792009-07-23 13:19:11 +02006624 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006625 }
6626 }
6627 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006628
Willy Tarreau6daf3432008-01-22 16:44:08 +01006629 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006630 err_code |= ERR_ALERT | ERR_FATAL;
6631 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006632 }
Willy Tarreau93893792009-07-23 13:19:11 +02006633 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006634 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006635 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006636}
6637
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006638int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006639cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6640{
6641#ifdef CONFIG_HAP_NS
6642 const char *err;
6643 const char *item = args[0];
6644
6645 if (!strcmp(item, "namespace_list")) {
6646 return 0;
6647 }
6648 else if (!strcmp(item, "namespace")) {
6649 size_t idx = 1;
6650 const char *current;
6651 while (*(current = args[idx++])) {
6652 err = invalid_char(current);
6653 if (err) {
6654 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6655 file, linenum, *err, item, current);
6656 return ERR_ALERT | ERR_FATAL;
6657 }
6658
6659 if (netns_store_lookup(current, strlen(current))) {
6660 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6661 file, linenum, current);
6662 return ERR_ALERT | ERR_FATAL;
6663 }
6664 if (!netns_store_insert(current)) {
6665 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6666 file, linenum, current);
6667 return ERR_ALERT | ERR_FATAL;
6668 }
6669 }
6670 }
6671
6672 return 0;
6673#else
6674 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6675 file, linenum);
6676 return ERR_ALERT | ERR_FATAL;
6677#endif
6678}
6679
6680int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006681cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6682{
6683
6684 int err_code = 0;
6685 const char *err;
6686
6687 if (!strcmp(args[0], "userlist")) { /* new userlist */
6688 struct userlist *newul;
6689
6690 if (!*args[1]) {
6691 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6692 file, linenum, args[0]);
6693 err_code |= ERR_ALERT | ERR_FATAL;
6694 goto out;
6695 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006696 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6697 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006698
6699 err = invalid_char(args[1]);
6700 if (err) {
6701 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6702 file, linenum, *err, args[0], args[1]);
6703 err_code |= ERR_ALERT | ERR_FATAL;
6704 goto out;
6705 }
6706
6707 for (newul = userlist; newul; newul = newul->next)
6708 if (!strcmp(newul->name, args[1])) {
6709 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6710 file, linenum, args[1]);
6711 err_code |= ERR_WARN;
6712 goto out;
6713 }
6714
6715 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6716 if (!newul) {
6717 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6718 err_code |= ERR_ALERT | ERR_ABORT;
6719 goto out;
6720 }
6721
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006722 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006723 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006724 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6725 err_code |= ERR_ALERT | ERR_ABORT;
6726 goto out;
6727 }
6728
6729 newul->next = userlist;
6730 userlist = newul;
6731
6732 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006733 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006734 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006735 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006736
6737 if (!*args[1]) {
6738 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6739 file, linenum, args[0]);
6740 err_code |= ERR_ALERT | ERR_FATAL;
6741 goto out;
6742 }
6743
6744 err = invalid_char(args[1]);
6745 if (err) {
6746 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6747 file, linenum, *err, args[0], args[1]);
6748 err_code |= ERR_ALERT | ERR_FATAL;
6749 goto out;
6750 }
6751
William Lallemand4ac9f542015-05-28 18:03:51 +02006752 if (!userlist)
6753 goto out;
6754
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006755 for (ag = userlist->groups; ag; ag = ag->next)
6756 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006757 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6758 file, linenum, args[1], userlist->name);
6759 err_code |= ERR_ALERT;
6760 goto out;
6761 }
6762
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006763 ag = calloc(1, sizeof(*ag));
6764 if (!ag) {
6765 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6766 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006767 goto out;
6768 }
6769
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006770 ag->name = strdup(args[1]);
6771 if (!ag) {
6772 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6773 err_code |= ERR_ALERT | ERR_ABORT;
6774 goto out;
6775 }
6776
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006777 cur_arg = 2;
6778
6779 while (*args[cur_arg]) {
6780 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006781 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006782 cur_arg += 2;
6783 continue;
6784 } else {
6785 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6786 file, linenum, args[0]);
6787 err_code |= ERR_ALERT | ERR_FATAL;
6788 goto out;
6789 }
6790 }
6791
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006792 ag->next = userlist->groups;
6793 userlist->groups = ag;
6794
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006795 } else if (!strcmp(args[0], "user")) { /* new user */
6796 struct auth_users *newuser;
6797 int cur_arg;
6798
6799 if (!*args[1]) {
6800 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6801 file, linenum, args[0]);
6802 err_code |= ERR_ALERT | ERR_FATAL;
6803 goto out;
6804 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006805 if (!userlist)
6806 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006807
6808 for (newuser = userlist->users; newuser; newuser = newuser->next)
6809 if (!strcmp(newuser->user, args[1])) {
6810 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6811 file, linenum, args[1], userlist->name);
6812 err_code |= ERR_ALERT;
6813 goto out;
6814 }
6815
6816 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6817 if (!newuser) {
6818 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6819 err_code |= ERR_ALERT | ERR_ABORT;
6820 goto out;
6821 }
6822
6823 newuser->user = strdup(args[1]);
6824
6825 newuser->next = userlist->users;
6826 userlist->users = newuser;
6827
6828 cur_arg = 2;
6829
6830 while (*args[cur_arg]) {
6831 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006832#ifdef CONFIG_HAP_CRYPT
6833 if (!crypt("", args[cur_arg + 1])) {
6834 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6835 file, linenum, newuser->user);
6836 err_code |= ERR_ALERT | ERR_FATAL;
6837 goto out;
6838 }
6839#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006840 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6841 file, linenum);
6842 err_code |= ERR_ALERT;
6843#endif
6844 newuser->pass = strdup(args[cur_arg + 1]);
6845 cur_arg += 2;
6846 continue;
6847 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6848 newuser->pass = strdup(args[cur_arg + 1]);
6849 newuser->flags |= AU_O_INSECURE;
6850 cur_arg += 2;
6851 continue;
6852 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006853 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006854 cur_arg += 2;
6855 continue;
6856 } else {
6857 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6858 file, linenum, args[0]);
6859 err_code |= ERR_ALERT | ERR_FATAL;
6860 goto out;
6861 }
6862 }
6863 } else {
6864 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6865 err_code |= ERR_ALERT | ERR_FATAL;
6866 }
6867
6868out:
6869 return err_code;
6870}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006871
6872/*
6873 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006874 * Returns the error code, 0 if OK, or any combination of :
6875 * - ERR_ABORT: must abort ASAP
6876 * - ERR_FATAL: we can continue parsing but not start the service
6877 * - ERR_WARN: a warning has been emitted
6878 * - ERR_ALERT: an alert has been emitted
6879 * Only the two first ones can stop processing, the two others are just
6880 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006881 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006882int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006883{
William Lallemand64e84512015-05-12 14:25:37 +02006884 char *thisline;
6885 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006886 FILE *f;
6887 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006888 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006889 struct cfg_section *cs = NULL;
6890 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006891 int readbytes = 0;
6892
6893 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006894 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006895 return -1;
6896 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006897
6898 /* Register internal sections */
6899 if (!cfg_register_section("listen", cfg_parse_listen) ||
6900 !cfg_register_section("frontend", cfg_parse_listen) ||
6901 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006902 !cfg_register_section("defaults", cfg_parse_listen) ||
6903 !cfg_register_section("global", cfg_parse_global) ||
6904 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006905 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006906 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006907 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6908 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006909 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006910
Willy Tarreaubaaee002006-06-26 02:48:02 +02006911 if ((f=fopen(file,"r")) == NULL)
6912 return -1;
6913
William Lallemandb2f07452015-05-12 14:27:13 +02006914next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006915 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006916 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006917 char *end;
6918 char *args[MAX_LINE_ARGS + 1];
6919 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006920 int dquote = 0; /* double quote */
6921 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006922
Willy Tarreaubaaee002006-06-26 02:48:02 +02006923 linenum++;
6924
6925 end = line + strlen(line);
6926
William Lallemand64e84512015-05-12 14:25:37 +02006927 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006928 /* Check if we reached the limit and the last char is not \n.
6929 * Watch out for the last line without the terminating '\n'!
6930 */
William Lallemand64e84512015-05-12 14:25:37 +02006931 char *newline;
6932 int newlinesize = linesize * 2;
6933
6934 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6935 if (newline == NULL) {
6936 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6937 file, linenum);
6938 err_code |= ERR_ALERT | ERR_FATAL;
6939 continue;
6940 }
6941
6942 readbytes = linesize - 1;
6943 linesize = newlinesize;
6944 thisline = newline;
6945 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006946 }
6947
William Lallemand64e84512015-05-12 14:25:37 +02006948 readbytes = 0;
6949
Willy Tarreaubaaee002006-06-26 02:48:02 +02006950 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006951 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006952 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006953
Willy Tarreaubaaee002006-06-26 02:48:02 +02006954 arg = 0;
6955 args[arg] = line;
6956
6957 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006958 if (*line == '"' && !squote) { /* double quote outside single quotes */
6959 if (dquote)
6960 dquote = 0;
6961 else
6962 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006963 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006964 end--;
6965 }
6966 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6967 if (squote)
6968 squote = 0;
6969 else
6970 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006971 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006972 end--;
6973 }
6974 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006975 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6976 * C equivalent value. Other combinations left unchanged (eg: \1).
6977 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006978 int skip = 0;
6979 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6980 *line = line[1];
6981 skip = 1;
6982 }
6983 else if (line[1] == 'r') {
6984 *line = '\r';
6985 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006986 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006987 else if (line[1] == 'n') {
6988 *line = '\n';
6989 skip = 1;
6990 }
6991 else if (line[1] == 't') {
6992 *line = '\t';
6993 skip = 1;
6994 }
6995 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006996 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006997 unsigned char hex1, hex2;
6998 hex1 = toupper(line[2]) - '0';
6999 hex2 = toupper(line[3]) - '0';
7000 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7001 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7002 *line = (hex1<<4) + hex2;
7003 skip = 3;
7004 }
7005 else {
7006 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007007 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007008 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007009 } else if (line[1] == '"') {
7010 *line = '"';
7011 skip = 1;
7012 } else if (line[1] == '\'') {
7013 *line = '\'';
7014 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007015 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7016 *line = '$';
7017 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007018 }
7019 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007020 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007021 end -= skip;
7022 }
7023 line++;
7024 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007025 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007026 /* end of string, end of loop */
7027 *line = 0;
7028 break;
7029 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007030 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007031 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007032 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007033 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007034 line++;
7035 args[++arg] = line;
7036 }
William Lallemandb2f07452015-05-12 14:27:13 +02007037 else if (dquote && *line == '$') {
7038 /* environment variables are evaluated inside double quotes */
7039 char *var_beg;
7040 char *var_end;
7041 char save_char;
7042 char *value;
7043 int val_len;
7044 int newlinesize;
7045 int braces = 0;
7046
7047 var_beg = line + 1;
7048 var_end = var_beg;
7049
7050 if (*var_beg == '{') {
7051 var_beg++;
7052 var_end++;
7053 braces = 1;
7054 }
7055
7056 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7057 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7058 err_code |= ERR_ALERT | ERR_FATAL;
7059 goto next_line; /* skip current line */
7060 }
7061
7062 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7063 var_end++;
7064
7065 save_char = *var_end;
7066 *var_end = '\0';
7067 value = getenv(var_beg);
7068 *var_end = save_char;
7069 val_len = value ? strlen(value) : 0;
7070
7071 if (braces) {
7072 if (*var_end == '}') {
7073 var_end++;
7074 braces = 0;
7075 } else {
7076 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7077 err_code |= ERR_ALERT | ERR_FATAL;
7078 goto next_line; /* skip current line */
7079 }
7080 }
7081
7082 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7083
7084 /* if not enough space in thisline */
7085 if (newlinesize > linesize) {
7086 char *newline;
7087
7088 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7089 if (newline == NULL) {
7090 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7091 err_code |= ERR_ALERT | ERR_FATAL;
7092 goto next_line; /* slip current line */
7093 }
7094 /* recompute pointers if realloc returns a new pointer */
7095 if (newline != thisline) {
7096 int i;
7097 int diff;
7098
7099 for (i = 0; i <= arg; i++) {
7100 diff = args[i] - thisline;
7101 args[i] = newline + diff;
7102 }
7103
7104 diff = var_end - thisline;
7105 var_end = newline + diff;
7106 diff = end - thisline;
7107 end = newline + diff;
7108 diff = line - thisline;
7109 line = newline + diff;
7110 thisline = newline;
7111 }
7112 linesize = newlinesize;
7113 }
7114
7115 /* insert value inside the line */
7116 memmove(line + val_len, var_end, end - var_end + 1);
7117 memcpy(line, value, val_len);
7118 end += val_len - (var_end - line);
7119 line += val_len;
7120 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007121 else {
7122 line++;
7123 }
7124 }
William Lallemandb2f07452015-05-12 14:27:13 +02007125
William Lallemandf9873ba2015-05-05 17:37:14 +02007126 if (dquote) {
7127 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7128 err_code |= ERR_ALERT | ERR_FATAL;
7129 }
7130
7131 if (squote) {
7132 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7133 err_code |= ERR_ALERT | ERR_FATAL;
7134 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007135
7136 /* empty line */
7137 if (!**args)
7138 continue;
7139
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007140 if (*line) {
7141 /* we had to stop due to too many args.
7142 * Let's terminate the string, print the offending part then cut the
7143 * last arg.
7144 */
7145 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7146 line++;
7147 *line = '\0';
7148
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007149 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007150 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007151 err_code |= ERR_ALERT | ERR_FATAL;
7152 args[arg] = line;
7153 }
7154
Willy Tarreau540abe42007-05-02 20:50:16 +02007155 /* zero out remaining args and ensure that at least one entry
7156 * is zeroed out.
7157 */
7158 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007159 args[arg] = line;
7160 }
7161
Willy Tarreau3842f002009-06-14 11:39:52 +02007162 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007163 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007164 char *tmp;
7165
Willy Tarreau3842f002009-06-14 11:39:52 +02007166 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007167 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007168 for (arg=0; *args[arg+1]; arg++)
7169 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007170 *tmp = '\0'; // fix the next arg to \0
7171 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007172 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007173 else if (!strcmp(args[0], "default")) {
7174 kwm = KWM_DEF;
7175 for (arg=0; *args[arg+1]; arg++)
7176 args[arg] = args[arg+1]; // shift args after inversion
7177 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007178
William Lallemand0f99e342011-10-12 17:50:54 +02007179 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7180 strcmp(args[0], "log") != 0) {
7181 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007182 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007183 }
7184
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007185 /* detect section start */
7186 list_for_each_entry(ics, &sections, list) {
7187 if (strcmp(args[0], ics->section_name) == 0) {
7188 cursection = ics->section_name;
7189 cs = ics;
7190 break;
7191 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007192 }
7193
Willy Tarreaubaaee002006-06-26 02:48:02 +02007194 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007195 if (cs)
7196 err_code |= cs->section_parser(file, linenum, args, kwm);
7197 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007198 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007199 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007200 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007201
7202 if (err_code & ERR_ABORT)
7203 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007204 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007205 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007206 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007207 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007208 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007209}
7210
Willy Tarreau64ab6072014-09-16 12:17:36 +02007211/* This function propagates processes from frontend <from> to backend <to> so
7212 * that it is always guaranteed that a backend pointed to by a frontend is
7213 * bound to all of its processes. After that, if the target is a "listen"
7214 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007215 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007216 * checked first to ensure that <to> is already bound to all processes of
7217 * <from>, there is no risk of looping and we ensure to follow the shortest
7218 * path to the destination.
7219 *
7220 * It is possible to set <to> to NULL for the first call so that the function
7221 * takes care of visiting the initial frontend in <from>.
7222 *
7223 * It is important to note that the function relies on the fact that all names
7224 * have already been resolved.
7225 */
7226void propagate_processes(struct proxy *from, struct proxy *to)
7227{
7228 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007229
7230 if (to) {
7231 /* check whether we need to go down */
7232 if (from->bind_proc &&
7233 (from->bind_proc & to->bind_proc) == from->bind_proc)
7234 return;
7235
7236 if (!from->bind_proc && !to->bind_proc)
7237 return;
7238
7239 to->bind_proc = from->bind_proc ?
7240 (to->bind_proc | from->bind_proc) : 0;
7241
7242 /* now propagate down */
7243 from = to;
7244 }
7245
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007246 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007247 return;
7248
Willy Tarreauf6b70012014-12-18 14:00:43 +01007249 if (from->state == PR_STSTOPPED)
7250 return;
7251
Willy Tarreau64ab6072014-09-16 12:17:36 +02007252 /* default_backend */
7253 if (from->defbe.be)
7254 propagate_processes(from, from->defbe.be);
7255
7256 /* use_backend */
7257 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007258 if (rule->dynamic)
7259 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007260 to = rule->be.backend;
7261 propagate_processes(from, to);
7262 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007263}
7264
Willy Tarreaubb925012009-07-23 13:36:36 +02007265/*
7266 * Returns the error code, 0 if OK, or any combination of :
7267 * - ERR_ABORT: must abort ASAP
7268 * - ERR_FATAL: we can continue parsing but not start the service
7269 * - ERR_WARN: a warning has been emitted
7270 * - ERR_ALERT: an alert has been emitted
7271 * Only the two first ones can stop processing, the two others are just
7272 * indicators.
7273 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007274int check_config_validity()
7275{
7276 int cfgerr = 0;
7277 struct proxy *curproxy = NULL;
7278 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007279 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007280 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007281 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007282
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007283 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007284 /*
7285 * Now, check for the integrity of all that we have collected.
7286 */
7287
7288 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007289 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007290
Willy Tarreau193b8c62012-11-22 00:17:38 +01007291 if (!global.tune.max_http_hdr)
7292 global.tune.max_http_hdr = MAX_HTTP_HDR;
7293
7294 if (!global.tune.cookie_len)
7295 global.tune.cookie_len = CAPTURE_LEN;
7296
7297 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7298
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007299 /* Post initialisation of the users and groups lists. */
7300 err_code = userlist_postinit();
7301 if (err_code != ERR_NONE)
7302 goto out;
7303
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007304 /* first, we will invert the proxy list order */
7305 curproxy = NULL;
7306 while (proxy) {
7307 struct proxy *next;
7308
7309 next = proxy->next;
7310 proxy->next = curproxy;
7311 curproxy = proxy;
7312 if (!next)
7313 break;
7314 proxy = next;
7315 }
7316
Willy Tarreau419ead82014-09-16 13:41:21 +02007317 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007318 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007319 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007320 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007321 struct act_rule *trule;
7322 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007323 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007324 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007325 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007326
Willy Tarreau050536d2012-10-04 08:47:34 +02007327 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007328 /* proxy ID not set, use automatic numbering with first
7329 * spare entry starting with next_pxid.
7330 */
7331 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7332 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7333 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007334 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007335 next_pxid++;
7336
Willy Tarreau55ea7572007-06-17 19:56:27 +02007337
Willy Tarreaubaaee002006-06-26 02:48:02 +02007338 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007339 /* ensure we don't keep listeners uselessly bound */
7340 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007341 free((void *)curproxy->table.peers.name);
7342 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007343 continue;
7344 }
7345
Willy Tarreau102df612014-05-07 23:56:38 +02007346 /* Check multi-process mode compatibility for the current proxy */
7347
7348 if (curproxy->bind_proc) {
7349 /* an explicit bind-process was specified, let's check how many
7350 * processes remain.
7351 */
David Carliere6c39412015-07-02 07:00:17 +00007352 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007353
7354 curproxy->bind_proc &= nbits(global.nbproc);
7355 if (!curproxy->bind_proc && nbproc == 1) {
7356 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);
7357 curproxy->bind_proc = 1;
7358 }
7359 else if (!curproxy->bind_proc && nbproc > 1) {
7360 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);
7361 curproxy->bind_proc = 0;
7362 }
7363 }
7364
Willy Tarreau3d209582014-05-09 17:06:11 +02007365 /* check and reduce the bind-proc of each listener */
7366 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7367 unsigned long mask;
7368
7369 if (!bind_conf->bind_proc)
7370 continue;
7371
7372 mask = nbits(global.nbproc);
7373 if (curproxy->bind_proc)
7374 mask &= curproxy->bind_proc;
7375 /* mask cannot be null here thanks to the previous checks */
7376
David Carliere6c39412015-07-02 07:00:17 +00007377 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007378 bind_conf->bind_proc &= mask;
7379
7380 if (!bind_conf->bind_proc && nbproc == 1) {
7381 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",
7382 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7383 bind_conf->bind_proc = mask & ~(mask - 1);
7384 }
7385 else if (!bind_conf->bind_proc && nbproc > 1) {
7386 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",
7387 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7388 bind_conf->bind_proc = 0;
7389 }
7390 }
7391
Willy Tarreauff01a212009-03-15 13:46:16 +01007392 switch (curproxy->mode) {
7393 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007394 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007395 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007396 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7397 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007398 cfgerr++;
7399 }
7400
7401 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007402 Warning("config : servers will be ignored for %s '%s'.\n",
7403 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007404 break;
7405
7406 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007407 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007408 break;
7409
7410 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007411 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007412 break;
7413 }
7414
Willy Tarreauf3934b82015-08-11 11:36:45 +02007415 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7416 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7417 proxy_type_str(curproxy), curproxy->id);
7418 err_code |= ERR_WARN;
7419 }
7420
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007421 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007422 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007423 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007424 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7425 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007426 cfgerr++;
7427 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007428#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007429 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007430 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7431 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007432 cfgerr++;
7433 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007434#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007435 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007436 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7437 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007438 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007439 }
7440 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007441 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007442 /* If no LB algo is set in a backend, and we're not in
7443 * transparent mode, dispatch mode nor proxy mode, we
7444 * want to use balance roundrobin by default.
7445 */
7446 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7447 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007448 }
7449 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007450
Willy Tarreau1620ec32011-08-06 17:05:02 +02007451 if (curproxy->options & PR_O_DISPATCH)
7452 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7453 else if (curproxy->options & PR_O_HTTP_PROXY)
7454 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7455 else if (curproxy->options & PR_O_TRANSP)
7456 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007457
Willy Tarreau1620ec32011-08-06 17:05:02 +02007458 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7459 if (curproxy->options & PR_O_DISABLE404) {
7460 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7461 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7462 err_code |= ERR_WARN;
7463 curproxy->options &= ~PR_O_DISABLE404;
7464 }
7465 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7466 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7467 "send-state", proxy_type_str(curproxy), curproxy->id);
7468 err_code |= ERR_WARN;
7469 curproxy->options &= ~PR_O2_CHK_SNDST;
7470 }
Willy Tarreauef781042010-01-27 11:53:01 +01007471 }
7472
Simon Horman98637e52014-06-20 12:30:16 +09007473 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7474 if (!global.external_check) {
7475 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7476 curproxy->id, "option external-check");
7477 cfgerr++;
7478 }
7479 if (!curproxy->check_command) {
7480 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7481 curproxy->id, "option external-check");
7482 cfgerr++;
7483 }
7484 }
7485
Simon Horman64e34162015-02-06 11:11:57 +09007486 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007487 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7488 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007489 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7490 "'email-alert myhostname', or 'email-alert to' "
7491 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007492 "to be present).\n",
7493 proxy_type_str(curproxy), curproxy->id);
7494 err_code |= ERR_WARN;
7495 free_email_alert(curproxy);
7496 }
7497 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007498 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007499 }
7500
Simon Horman98637e52014-06-20 12:30:16 +09007501 if (curproxy->check_command) {
7502 int clear = 0;
7503 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7504 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7505 "external-check command", proxy_type_str(curproxy), curproxy->id);
7506 err_code |= ERR_WARN;
7507 clear = 1;
7508 }
7509 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007510 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007511 curproxy->id, "external-check command");
7512 cfgerr++;
7513 }
7514 if (clear) {
7515 free(curproxy->check_command);
7516 curproxy->check_command = NULL;
7517 }
7518 }
7519
7520 if (curproxy->check_path) {
7521 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7522 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7523 "external-check path", proxy_type_str(curproxy), curproxy->id);
7524 err_code |= ERR_WARN;
7525 free(curproxy->check_path);
7526 curproxy->check_path = NULL;
7527 }
7528 }
7529
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007530 /* if a default backend was specified, let's find it */
7531 if (curproxy->defbe.name) {
7532 struct proxy *target;
7533
Willy Tarreauafb39922015-05-26 12:04:09 +02007534 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007535 if (!target) {
7536 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7537 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007538 cfgerr++;
7539 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007540 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7541 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007542 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007543 } else if (target->mode != curproxy->mode &&
7544 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7545
7546 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7547 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7548 curproxy->conf.file, curproxy->conf.line,
7549 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7550 target->conf.file, target->conf.line);
7551 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007552 } else {
7553 free(curproxy->defbe.name);
7554 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007555
7556 /* Emit a warning if this proxy also has some servers */
7557 if (curproxy->srv) {
7558 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7559 curproxy->id);
7560 err_code |= ERR_WARN;
7561 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007562 }
7563 }
7564
Willy Tarreau55ea7572007-06-17 19:56:27 +02007565 /* find the target proxy for 'use_backend' rules */
7566 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007567 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007568 struct logformat_node *node;
7569 char *pxname;
7570
7571 /* Try to parse the string as a log format expression. If the result
7572 * of the parsing is only one entry containing a simple string, then
7573 * it's a standard string corresponding to a static rule, thus the
7574 * parsing is cancelled and be.name is restored to be resolved.
7575 */
7576 pxname = rule->be.name;
7577 LIST_INIT(&rule->be.expr);
7578 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7579 curproxy->conf.args.file, curproxy->conf.args.line);
7580 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7581
7582 if (!LIST_ISEMPTY(&rule->be.expr)) {
7583 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7584 rule->dynamic = 1;
7585 free(pxname);
7586 continue;
7587 }
7588 /* simple string: free the expression and fall back to static rule */
7589 free(node->arg);
7590 free(node);
7591 }
7592
7593 rule->dynamic = 0;
7594 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007595
Willy Tarreauafb39922015-05-26 12:04:09 +02007596 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007597 if (!target) {
7598 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7599 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007600 cfgerr++;
7601 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007602 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7603 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007604 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007605 } else if (target->mode != curproxy->mode &&
7606 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7607
7608 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7609 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7610 curproxy->conf.file, curproxy->conf.line,
7611 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7612 target->conf.file, target->conf.line);
7613 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007614 } else {
7615 free((void *)rule->be.name);
7616 rule->be.backend = target;
7617 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007618 }
7619
Willy Tarreau64ab6072014-09-16 12:17:36 +02007620 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007621 list_for_each_entry(srule, &curproxy->server_rules, list) {
7622 struct server *target = findserver(curproxy, srule->srv.name);
7623
7624 if (!target) {
7625 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7626 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7627 cfgerr++;
7628 continue;
7629 }
7630 free((void *)srule->srv.name);
7631 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007632 }
7633
Emeric Brunb982a3d2010-01-04 15:45:53 +01007634 /* find the target table for 'stick' rules */
7635 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7636 struct proxy *target;
7637
Emeric Brun1d33b292010-01-04 15:47:17 +01007638 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7639 if (mrule->flags & STK_IS_STORE)
7640 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7641
Emeric Brunb982a3d2010-01-04 15:45:53 +01007642 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007643 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007644 else
7645 target = curproxy;
7646
7647 if (!target) {
7648 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7649 curproxy->id, mrule->table.name);
7650 cfgerr++;
7651 }
7652 else if (target->table.size == 0) {
7653 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7654 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7655 cfgerr++;
7656 }
Willy Tarreau12785782012-04-27 21:37:17 +02007657 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7658 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007659 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7660 cfgerr++;
7661 }
7662 else {
7663 free((void *)mrule->table.name);
7664 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007665 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007666 }
7667 }
7668
7669 /* find the target table for 'store response' rules */
7670 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7671 struct proxy *target;
7672
Emeric Brun1d33b292010-01-04 15:47:17 +01007673 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7674
Emeric Brunb982a3d2010-01-04 15:45:53 +01007675 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007676 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007677 else
7678 target = curproxy;
7679
7680 if (!target) {
7681 Alert("Proxy '%s': unable to find store table '%s'.\n",
7682 curproxy->id, mrule->table.name);
7683 cfgerr++;
7684 }
7685 else if (target->table.size == 0) {
7686 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7687 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7688 cfgerr++;
7689 }
Willy Tarreau12785782012-04-27 21:37:17 +02007690 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7691 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007692 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7693 cfgerr++;
7694 }
7695 else {
7696 free((void *)mrule->table.name);
7697 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007698 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007699 }
7700 }
7701
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007702 /* find the target table for 'tcp-request' layer 4 rules */
7703 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7704 struct proxy *target;
7705
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007706 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007707 continue;
7708
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007709 if (trule->arg.trk_ctr.table.n)
7710 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007711 else
7712 target = curproxy;
7713
7714 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007715 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007716 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007717 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007718 cfgerr++;
7719 }
7720 else if (target->table.size == 0) {
7721 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007722 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007723 cfgerr++;
7724 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007725 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007726 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007727 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007728 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007729 cfgerr++;
7730 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007731 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007732 free(trule->arg.trk_ctr.table.n);
7733 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007734 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007735 * to pass a list of counters to track and allocate them right here using
7736 * stktable_alloc_data_type().
7737 */
7738 }
7739 }
7740
Willy Tarreaud1f96522010-08-03 19:34:32 +02007741 /* find the target table for 'tcp-request' layer 6 rules */
7742 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7743 struct proxy *target;
7744
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007745 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007746 continue;
7747
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007748 if (trule->arg.trk_ctr.table.n)
7749 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007750 else
7751 target = curproxy;
7752
7753 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007754 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007755 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007756 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007757 cfgerr++;
7758 }
7759 else if (target->table.size == 0) {
7760 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007761 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007762 cfgerr++;
7763 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007764 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007765 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007766 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007767 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007768 cfgerr++;
7769 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007770 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007771 free(trule->arg.trk_ctr.table.n);
7772 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007773 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007774 * to pass a list of counters to track and allocate them right here using
7775 * stktable_alloc_data_type().
7776 */
7777 }
7778 }
7779
Baptiste Assmanne9544932015-11-03 23:31:35 +01007780 /* parse http-request capture rules to ensure id really exists */
7781 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7782 if (hrqrule->action != ACT_CUSTOM ||
7783 hrqrule->action_ptr != http_action_req_capture_by_id)
7784 continue;
7785
7786 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7787 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7788 curproxy->id, hrqrule->arg.capid.idx);
7789 cfgerr++;
7790 }
7791 }
7792
7793 /* parse http-response capture rules to ensure id really exists */
7794 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7795 if (hrqrule->action != ACT_CUSTOM ||
7796 hrqrule->action_ptr != http_action_res_capture_by_id)
7797 continue;
7798
7799 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7800 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7801 curproxy->id, hrqrule->arg.capid.idx);
7802 cfgerr++;
7803 }
7804 }
7805
Willy Tarreau09448f72014-06-25 18:12:15 +02007806 /* find the target table for 'http-request' layer 7 rules */
7807 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7808 struct proxy *target;
7809
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007810 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007811 continue;
7812
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007813 if (hrqrule->arg.trk_ctr.table.n)
7814 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007815 else
7816 target = curproxy;
7817
7818 if (!target) {
7819 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007820 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007821 http_req_trk_idx(hrqrule->action));
7822 cfgerr++;
7823 }
7824 else if (target->table.size == 0) {
7825 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007826 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007827 cfgerr++;
7828 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007829 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007830 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007831 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007832 http_req_trk_idx(hrqrule->action));
7833 cfgerr++;
7834 }
7835 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007836 free(hrqrule->arg.trk_ctr.table.n);
7837 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007838 /* Note: if we decide to enhance the track-sc syntax, we may be able
7839 * to pass a list of counters to track and allocate them right here using
7840 * stktable_alloc_data_type().
7841 */
7842 }
7843 }
7844
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007845 /* move any "block" rules at the beginning of the http-request rules */
7846 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7847 /* insert block_rules into http_req_rules at the beginning */
7848 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7849 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7850 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7851 curproxy->http_req_rules.n = curproxy->block_rules.n;
7852 LIST_INIT(&curproxy->block_rules);
7853 }
7854
Emeric Brun32da3c42010-09-23 18:39:19 +02007855 if (curproxy->table.peers.name) {
7856 struct peers *curpeers = peers;
7857
7858 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7859 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7860 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007861 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007862 break;
7863 }
7864 }
7865
7866 if (!curpeers) {
7867 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7868 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007869 free((void *)curproxy->table.peers.name);
7870 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007871 cfgerr++;
7872 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007873 else if (curpeers->state == PR_STSTOPPED) {
7874 /* silently disable this peers section */
7875 curproxy->table.peers.p = NULL;
7876 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007877 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007878 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7879 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007880 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007881 cfgerr++;
7882 }
7883 }
7884
Simon Horman9dc49962015-01-30 11:22:59 +09007885
7886 if (curproxy->email_alert.mailers.name) {
7887 struct mailers *curmailers = mailers;
7888
7889 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7890 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7891 free(curproxy->email_alert.mailers.name);
7892 curproxy->email_alert.mailers.m = curmailers;
7893 curmailers->users++;
7894 break;
7895 }
7896 }
7897
7898 if (!curmailers) {
7899 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7900 curproxy->id, curproxy->email_alert.mailers.name);
7901 free_email_alert(curproxy);
7902 cfgerr++;
7903 }
7904 }
7905
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007906 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007907 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007908 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7909 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7910 "proxy", curproxy->id);
7911 cfgerr++;
7912 goto out_uri_auth_compat;
7913 }
7914
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007915 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007916 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007917 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007918 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007919
Willy Tarreau95fa4692010-02-01 13:05:50 +01007920 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7921 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007922
7923 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007924 uri_auth_compat_req[i++] = "realm";
7925 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7926 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007927
Willy Tarreau95fa4692010-02-01 13:05:50 +01007928 uri_auth_compat_req[i++] = "unless";
7929 uri_auth_compat_req[i++] = "{";
7930 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7931 uri_auth_compat_req[i++] = "}";
7932 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007933
Willy Tarreauff011f22011-01-06 17:51:27 +01007934 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7935 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007936 cfgerr++;
7937 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007938 }
7939
Willy Tarreauff011f22011-01-06 17:51:27 +01007940 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007941
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007942 if (curproxy->uri_auth->auth_realm) {
7943 free(curproxy->uri_auth->auth_realm);
7944 curproxy->uri_auth->auth_realm = NULL;
7945 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007946
7947 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007948 }
7949out_uri_auth_compat:
7950
Dragan Dosen43885c72015-10-01 13:18:13 +02007951 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02007952 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02007953 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
7954 if (!curproxy->conf.logformat_sd_string) {
7955 /* set the default logformat_sd_string */
7956 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
7957 }
Dragan Dosen1322d092015-09-22 16:05:32 +02007958 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02007959 }
Dragan Dosen1322d092015-09-22 16:05:32 +02007960 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02007961
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007962 /* compile the log format */
7963 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007964 if (curproxy->conf.logformat_string != default_http_log_format &&
7965 curproxy->conf.logformat_string != default_tcp_log_format &&
7966 curproxy->conf.logformat_string != clf_http_log_format)
7967 free(curproxy->conf.logformat_string);
7968 curproxy->conf.logformat_string = NULL;
7969 free(curproxy->conf.lfs_file);
7970 curproxy->conf.lfs_file = NULL;
7971 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007972
7973 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
7974 free(curproxy->conf.logformat_sd_string);
7975 curproxy->conf.logformat_sd_string = NULL;
7976 free(curproxy->conf.lfsd_file);
7977 curproxy->conf.lfsd_file = NULL;
7978 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007979 }
7980
Willy Tarreau62a61232013-04-12 18:13:46 +02007981 if (curproxy->conf.logformat_string) {
7982 curproxy->conf.args.ctx = ARGC_LOG;
7983 curproxy->conf.args.file = curproxy->conf.lfs_file;
7984 curproxy->conf.args.line = curproxy->conf.lfs_line;
7985 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007986 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007987 curproxy->conf.args.file = NULL;
7988 curproxy->conf.args.line = 0;
7989 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007990
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007991 if (curproxy->conf.logformat_sd_string) {
7992 curproxy->conf.args.ctx = ARGC_LOGSD;
7993 curproxy->conf.args.file = curproxy->conf.lfsd_file;
7994 curproxy->conf.args.line = curproxy->conf.lfsd_line;
7995 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
7996 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
7997 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
7998 curproxy->conf.args.file = NULL;
7999 curproxy->conf.args.line = 0;
8000 }
8001
Willy Tarreau62a61232013-04-12 18:13:46 +02008002 if (curproxy->conf.uniqueid_format_string) {
8003 curproxy->conf.args.ctx = ARGC_UIF;
8004 curproxy->conf.args.file = curproxy->conf.uif_file;
8005 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01008006 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08008007 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008008 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008009 curproxy->conf.args.file = NULL;
8010 curproxy->conf.args.line = 0;
8011 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008012
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008013 /* only now we can check if some args remain unresolved.
8014 * This must be done after the users and groups resolution.
8015 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008016 cfgerr += smp_resolve_args(curproxy);
8017 if (!cfgerr)
8018 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008019
Willy Tarreau2738a142006-07-08 17:28:09 +02008020 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008021 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008022 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008023 (!curproxy->timeout.connect ||
8024 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008025 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008026 " | While not properly invalid, you will certainly encounter various problems\n"
8027 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008028 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008029 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008030 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008031 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008032
Willy Tarreau1fa31262007-12-03 00:36:16 +01008033 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8034 * We must still support older configurations, so let's find out whether those
8035 * parameters have been set or must be copied from contimeouts.
8036 */
8037 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008038 if (!curproxy->timeout.tarpit ||
8039 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008040 /* tarpit timeout not set. We search in the following order:
8041 * default.tarpit, curr.connect, default.connect.
8042 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008043 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008044 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008045 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008046 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008047 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008048 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008049 }
8050 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008051 (!curproxy->timeout.queue ||
8052 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008053 /* queue timeout not set. We search in the following order:
8054 * default.queue, curr.connect, default.connect.
8055 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008056 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008057 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008058 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008059 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008060 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008061 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008062 }
8063 }
8064
Willy Tarreau1620ec32011-08-06 17:05:02 +02008065 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008066 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
8067 curproxy->check_req = (char *)malloc(curproxy->check_len);
8068 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008069 }
8070
Willy Tarreau215663d2014-06-13 18:30:23 +02008071 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8072 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8073 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8074 proxy_type_str(curproxy), curproxy->id);
8075 err_code |= ERR_WARN;
8076 }
8077
Willy Tarreau193b8c62012-11-22 00:17:38 +01008078 /* ensure that cookie capture length is not too large */
8079 if (curproxy->capture_len >= global.tune.cookie_len) {
8080 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8081 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8082 err_code |= ERR_WARN;
8083 curproxy->capture_len = global.tune.cookie_len - 1;
8084 }
8085
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008086 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008087 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008088 curproxy->req_cap_pool = create_pool("ptrcap",
8089 curproxy->nb_req_cap * sizeof(char *),
8090 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008091 }
8092
8093 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008094 curproxy->rsp_cap_pool = create_pool("ptrcap",
8095 curproxy->nb_rsp_cap * sizeof(char *),
8096 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008097 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008098
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008099 switch (curproxy->load_server_state_from_file) {
8100 case PR_SRV_STATE_FILE_UNSPEC:
8101 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8102 break;
8103 case PR_SRV_STATE_FILE_GLOBAL:
8104 if (!global.server_state_file) {
8105 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",
8106 curproxy->id);
8107 err_code |= ERR_WARN;
8108 }
8109 break;
8110 }
8111
Willy Tarreaubaaee002006-06-26 02:48:02 +02008112 /* first, we will invert the servers list order */
8113 newsrv = NULL;
8114 while (curproxy->srv) {
8115 struct server *next;
8116
8117 next = curproxy->srv->next;
8118 curproxy->srv->next = newsrv;
8119 newsrv = curproxy->srv;
8120 if (!next)
8121 break;
8122 curproxy->srv = next;
8123 }
8124
Willy Tarreau17edc812014-01-03 12:14:34 +01008125 /* Check that no server name conflicts. This causes trouble in the stats.
8126 * We only emit a warning for the first conflict affecting each server,
8127 * in order to avoid combinatory explosion if all servers have the same
8128 * name. We do that only for servers which do not have an explicit ID,
8129 * because these IDs were made also for distinguishing them and we don't
8130 * want to annoy people who correctly manage them.
8131 */
8132 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8133 struct server *other_srv;
8134
8135 if (newsrv->puid)
8136 continue;
8137
8138 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8139 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8140 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8141 newsrv->conf.file, newsrv->conf.line,
8142 proxy_type_str(curproxy), curproxy->id,
8143 newsrv->id, other_srv->conf.line);
8144 break;
8145 }
8146 }
8147 }
8148
Willy Tarreaudd701652010-05-25 23:03:02 +02008149 /* assign automatic UIDs to servers which don't have one yet */
8150 next_id = 1;
8151 newsrv = curproxy->srv;
8152 while (newsrv != NULL) {
8153 if (!newsrv->puid) {
8154 /* server ID not set, use automatic numbering with first
8155 * spare entry starting with next_svid.
8156 */
8157 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8158 newsrv->conf.id.key = newsrv->puid = next_id;
8159 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8160 }
8161 next_id++;
8162 newsrv = newsrv->next;
8163 }
8164
Willy Tarreau20697042007-11-15 23:26:18 +01008165 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008166 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008167
Willy Tarreau62c3be22012-01-20 13:12:32 +01008168 /*
8169 * If this server supports a maxconn parameter, it needs a dedicated
8170 * tasks to fill the emptied slots when a connection leaves.
8171 * Also, resolve deferred tracking dependency if needed.
8172 */
8173 newsrv = curproxy->srv;
8174 while (newsrv != NULL) {
8175 if (newsrv->minconn > newsrv->maxconn) {
8176 /* Only 'minconn' was specified, or it was higher than or equal
8177 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8178 * this will avoid further useless expensive computations.
8179 */
8180 newsrv->maxconn = newsrv->minconn;
8181 } else if (newsrv->maxconn && !newsrv->minconn) {
8182 /* minconn was not specified, so we set it to maxconn */
8183 newsrv->minconn = newsrv->maxconn;
8184 }
8185
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008186#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008187 if (newsrv->use_ssl || newsrv->check.use_ssl)
8188 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008189#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008190
Willy Tarreau2f075e92013-12-03 11:11:34 +01008191 /* set the check type on the server */
8192 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8193
Willy Tarreau62c3be22012-01-20 13:12:32 +01008194 if (newsrv->trackit) {
8195 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008196 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008197 char *pname, *sname;
8198
8199 pname = newsrv->trackit;
8200 sname = strrchr(pname, '/');
8201
8202 if (sname)
8203 *sname++ = '\0';
8204 else {
8205 sname = pname;
8206 pname = NULL;
8207 }
8208
8209 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008210 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008211 if (!px) {
8212 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8213 proxy_type_str(curproxy), curproxy->id,
8214 newsrv->id, pname);
8215 cfgerr++;
8216 goto next_srv;
8217 }
8218 } else
8219 px = curproxy;
8220
8221 srv = findserver(px, sname);
8222 if (!srv) {
8223 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8224 proxy_type_str(curproxy), curproxy->id,
8225 newsrv->id, sname);
8226 cfgerr++;
8227 goto next_srv;
8228 }
8229
Willy Tarreau32091232014-05-16 13:52:00 +02008230 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8231 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8232 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008233 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008234 "tracking as it does not have any check nor agent enabled.\n",
8235 proxy_type_str(curproxy), curproxy->id,
8236 newsrv->id, px->id, srv->id);
8237 cfgerr++;
8238 goto next_srv;
8239 }
8240
8241 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8242
8243 if (loop) {
8244 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8245 "belongs to a tracking chain looping back to %s/%s.\n",
8246 proxy_type_str(curproxy), curproxy->id,
8247 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008248 cfgerr++;
8249 goto next_srv;
8250 }
8251
8252 if (curproxy != px &&
8253 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8254 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8255 "tracking: disable-on-404 option inconsistency.\n",
8256 proxy_type_str(curproxy), curproxy->id,
8257 newsrv->id, px->id, srv->id);
8258 cfgerr++;
8259 goto next_srv;
8260 }
8261
8262 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008263 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008264 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008265 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008266 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008267 }
8268
8269 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008270 newsrv->tracknext = srv->trackers;
8271 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008272
8273 free(newsrv->trackit);
8274 newsrv->trackit = NULL;
8275 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008276
8277 /*
8278 * resolve server's resolvers name and update the resolvers pointer
8279 * accordingly
8280 */
8281 if (newsrv->resolvers_id) {
8282 struct dns_resolvers *curr_resolvers;
8283 int found;
8284
8285 found = 0;
8286 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8287 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8288 found = 1;
8289 break;
8290 }
8291 }
8292
8293 if (!found) {
8294 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8295 proxy_type_str(curproxy), curproxy->id,
8296 newsrv->id, newsrv->resolvers_id);
8297 cfgerr++;
8298 } else {
8299 free(newsrv->resolvers_id);
8300 newsrv->resolvers_id = NULL;
8301 if (newsrv->resolution)
8302 newsrv->resolution->resolvers = curr_resolvers;
8303 }
8304 }
8305 else {
8306 /* if no resolvers section associated to this server
8307 * we can clean up the associated resolution structure
8308 */
8309 if (newsrv->resolution) {
8310 free(newsrv->resolution->hostname_dn);
8311 newsrv->resolution->hostname_dn = NULL;
8312 free(newsrv->resolution);
8313 newsrv->resolution = NULL;
8314 }
8315 }
8316
Willy Tarreau62c3be22012-01-20 13:12:32 +01008317 next_srv:
8318 newsrv = newsrv->next;
8319 }
8320
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008321 /* We have to initialize the server lookup mechanism depending
8322 * on what LB algorithm was choosen.
8323 */
8324
8325 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8326 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8327 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008328 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8329 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8330 init_server_map(curproxy);
8331 } else {
8332 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8333 fwrr_init_server_groups(curproxy);
8334 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008335 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008336
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008337 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008338 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8339 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8340 fwlc_init_server_tree(curproxy);
8341 } else {
8342 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8343 fas_init_server_tree(curproxy);
8344 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008345 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008346
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008347 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008348 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8349 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8350 chash_init_server_tree(curproxy);
8351 } else {
8352 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8353 init_server_map(curproxy);
8354 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008355 break;
8356 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008357
8358 if (curproxy->options & PR_O_LOGASAP)
8359 curproxy->to_log &= ~LW_BYTES;
8360
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008361 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008362 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8363 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008364 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8365 proxy_type_str(curproxy), curproxy->id);
8366 err_code |= ERR_WARN;
8367 }
8368
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008369 if (curproxy->mode != PR_MODE_HTTP) {
8370 int optnum;
8371
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008372 if (curproxy->uri_auth) {
8373 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8374 proxy_type_str(curproxy), curproxy->id);
8375 err_code |= ERR_WARN;
8376 curproxy->uri_auth = NULL;
8377 }
8378
Willy Tarreau87cf5142011-08-19 22:57:24 +02008379 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008380 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8381 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8382 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008383 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008384 }
8385
8386 if (curproxy->options & PR_O_ORGTO) {
8387 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8388 "originalto", proxy_type_str(curproxy), curproxy->id);
8389 err_code |= ERR_WARN;
8390 curproxy->options &= ~PR_O_ORGTO;
8391 }
8392
8393 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8394 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8395 (curproxy->cap & cfg_opts[optnum].cap) &&
8396 (curproxy->options & cfg_opts[optnum].val)) {
8397 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8398 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8399 err_code |= ERR_WARN;
8400 curproxy->options &= ~cfg_opts[optnum].val;
8401 }
8402 }
8403
8404 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8405 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8406 (curproxy->cap & cfg_opts2[optnum].cap) &&
8407 (curproxy->options2 & cfg_opts2[optnum].val)) {
8408 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8409 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8410 err_code |= ERR_WARN;
8411 curproxy->options2 &= ~cfg_opts2[optnum].val;
8412 }
8413 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008414
Willy Tarreau29fbe512015-08-20 19:35:14 +02008415#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008416 if (curproxy->conn_src.bind_hdr_occ) {
8417 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008418 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008419 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008420 err_code |= ERR_WARN;
8421 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008422#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008423 }
8424
Willy Tarreaubaaee002006-06-26 02:48:02 +02008425 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008426 * ensure that we're not cross-dressing a TCP server into HTTP.
8427 */
8428 newsrv = curproxy->srv;
8429 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008430 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008431 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8432 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008433 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008434 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008435
Willy Tarreau0cec3312011-10-31 13:49:26 +01008436 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8437 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8438 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8439 err_code |= ERR_WARN;
8440 }
8441
Willy Tarreauc93cd162014-05-13 15:54:22 +02008442 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008443 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8444 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8445 err_code |= ERR_WARN;
8446 }
8447
Willy Tarreau29fbe512015-08-20 19:35:14 +02008448#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008449 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8450 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008451 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 +01008452 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008453 err_code |= ERR_WARN;
8454 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008455#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008456 newsrv = newsrv->next;
8457 }
8458
Willy Tarreaue42bd962014-09-16 16:21:19 +02008459 /* check if we have a frontend with "tcp-request content" looking at L7
8460 * with no inspect-delay
8461 */
8462 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8463 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008464 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008465 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008466 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008467 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008468 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008469 break;
8470 }
8471
8472 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8473 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8474 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8475 " This means that these rules will randomly find their contents. This can be fixed by"
8476 " setting the tcp-request inspect-delay.\n",
8477 proxy_type_str(curproxy), curproxy->id);
8478 err_code |= ERR_WARN;
8479 }
8480 }
8481
Christopher Fauletd7c91962015-04-30 11:48:27 +02008482 /* Check filter configuration, if any */
8483 cfgerr += flt_check(curproxy);
8484
Willy Tarreauc1a21672009-08-16 22:37:44 +02008485 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008486 if (!curproxy->accept)
8487 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008488
Willy Tarreauc1a21672009-08-16 22:37:44 +02008489 if (curproxy->tcp_req.inspect_delay ||
8490 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008491 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008492
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008493 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008494 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008495 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008496 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008497
8498 /* both TCP and HTTP must check switching rules */
8499 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008500
8501 /* Add filters analyzers if needed */
8502 if (!LIST_ISEMPTY(&curproxy->filters)) {
8503 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8504 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
8505 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008506 }
8507
8508 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008509 if (curproxy->tcp_req.inspect_delay ||
8510 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8511 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8512
Emeric Brun97679e72010-09-23 17:56:44 +02008513 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8514 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8515
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008516 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008517 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008518 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008519 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008520
8521 /* If the backend does requires RDP cookie persistence, we have to
8522 * enable the corresponding analyser.
8523 */
8524 if (curproxy->options2 & PR_O2_RDPC_PRST)
8525 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008526
8527 /* Add filters analyzers if needed */
8528 if (!LIST_ISEMPTY(&curproxy->filters)) {
8529 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8530 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
8531 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008532 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008533 }
8534
8535 /***********************************************************/
8536 /* At this point, target names have already been resolved. */
8537 /***********************************************************/
8538
8539 /* Check multi-process mode compatibility */
8540
8541 if (global.nbproc > 1 && global.stats_fe) {
8542 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8543 unsigned long mask;
8544
8545 mask = nbits(global.nbproc);
8546 if (global.stats_fe->bind_proc)
8547 mask &= global.stats_fe->bind_proc;
8548
8549 if (bind_conf->bind_proc)
8550 mask &= bind_conf->bind_proc;
8551
8552 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008553 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008554 break;
8555 }
8556 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8557 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");
8558 }
8559 }
8560
8561 /* Make each frontend inherit bind-process from its listeners when not specified. */
8562 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8563 if (curproxy->bind_proc)
8564 continue;
8565
8566 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8567 unsigned long mask;
8568
Willy Tarreaue428b082015-05-04 21:57:58 +02008569 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008570 curproxy->bind_proc |= mask;
8571 }
8572
8573 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008574 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008575 }
8576
8577 if (global.stats_fe) {
8578 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8579 unsigned long mask;
8580
Willy Tarreaue428b082015-05-04 21:57:58 +02008581 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008582 global.stats_fe->bind_proc |= mask;
8583 }
8584 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008585 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008586 }
8587
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008588 /* propagate bindings from frontends to backends. Don't do it if there
8589 * are any fatal errors as we must not call it with unresolved proxies.
8590 */
8591 if (!cfgerr) {
8592 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8593 if (curproxy->cap & PR_CAP_FE)
8594 propagate_processes(curproxy, NULL);
8595 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008596 }
8597
8598 /* Bind each unbound backend to all processes when not specified. */
8599 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8600 if (curproxy->bind_proc)
8601 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008602 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008603 }
8604
8605 /*******************************************************/
8606 /* At this step, all proxies have a non-null bind_proc */
8607 /*******************************************************/
8608
8609 /* perform the final checks before creating tasks */
8610
8611 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8612 struct listener *listener;
8613 unsigned int next_id;
8614 int nbproc;
8615
David Carliere6c39412015-07-02 07:00:17 +00008616 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008617
Emeric Brunc52962f2012-11-15 18:28:02 +01008618#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008619 /* Configure SSL for each bind line.
8620 * Note: if configuration fails at some point, the ->ctx member
8621 * remains NULL so that listeners can later detach.
8622 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008623 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008624 int alloc_ctx;
8625
Emeric Brunc52962f2012-11-15 18:28:02 +01008626 if (!bind_conf->is_ssl) {
8627 if (bind_conf->default_ctx) {
8628 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8629 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8630 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008631 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008632 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008633 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008634 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008635 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008636 cfgerr++;
8637 continue;
8638 }
8639
Emeric Brun8dc60392014-05-09 13:52:00 +02008640 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008641 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008642 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8643 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");
8644 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008645 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008646 cfgerr++;
8647 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008648 }
8649
Emeric Brunfc0421f2012-09-07 17:30:07 +02008650 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008651 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008652
8653 /* initialize CA variables if the certificates generation is enabled */
8654 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008655 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008656#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008657
Willy Tarreaue6b98942007-10-29 01:09:36 +01008658 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008659 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008660 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008661 if (!listener->luid) {
8662 /* listener ID not set, use automatic numbering with first
8663 * spare entry starting with next_luid.
8664 */
8665 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8666 listener->conf.id.key = listener->luid = next_id;
8667 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008668 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008669 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008670
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008671 /* enable separate counters */
8672 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8673 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008674 if (!listener->name)
8675 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008676 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008677
Willy Tarreaue6b98942007-10-29 01:09:36 +01008678 if (curproxy->options & PR_O_TCP_NOLING)
8679 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008680 if (!listener->maxconn)
8681 listener->maxconn = curproxy->maxconn;
8682 if (!listener->backlog)
8683 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008684 if (!listener->maxaccept)
8685 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8686
8687 /* we want to have an optimal behaviour on single process mode to
8688 * maximize the work at once, but in multi-process we want to keep
8689 * some fairness between processes, so we target half of the max
8690 * number of events to be balanced over all the processes the proxy
8691 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8692 * used to disable the limit.
8693 */
8694 if (listener->maxaccept > 0) {
8695 if (nbproc > 1)
8696 listener->maxaccept = (listener->maxaccept + 1) / 2;
8697 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8698 }
8699
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008700 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008701 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008702 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008703 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008704
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008705 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8706 listener->options |= LI_O_TCP_RULES;
8707
Willy Tarreaude3041d2010-05-31 10:56:17 +02008708 if (curproxy->mon_mask.s_addr)
8709 listener->options |= LI_O_CHK_MONNET;
8710
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008711 /* smart accept mode is automatic in HTTP mode */
8712 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008713 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008714 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8715 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008716 }
8717
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008718 /* Release unused SSL configs */
8719 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8720 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008721 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008722#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008723 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008724 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008725 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008726 free(bind_conf->ca_sign_file);
8727 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008728 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008729 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008730 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008731 if(bind_conf->keys_ref) {
8732 free(bind_conf->keys_ref->filename);
8733 free(bind_conf->keys_ref->tlskeys);
8734 free(bind_conf->keys_ref);
8735 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008736#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008737 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008738
Willy Tarreau102df612014-05-07 23:56:38 +02008739 if (nbproc > 1) {
8740 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008741 int count, maxproc = 0;
8742
8743 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008744 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008745 if (count > maxproc)
8746 maxproc = count;
8747 }
8748 /* backends have 0, frontends have 1 or more */
8749 if (maxproc != 1)
8750 Warning("Proxy '%s': in multi-process mode, stats will be"
8751 " limited to process assigned to the current request.\n",
8752 curproxy->id);
8753
Willy Tarreau102df612014-05-07 23:56:38 +02008754 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8755 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8756 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008757 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008758 }
Willy Tarreau102df612014-05-07 23:56:38 +02008759 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8760 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8761 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008762 }
8763 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008764
8765 /* create the task associated with the proxy */
8766 curproxy->task = task_new();
8767 if (curproxy->task) {
8768 curproxy->task->context = curproxy;
8769 curproxy->task->process = manage_proxy;
8770 /* no need to queue, it will be done automatically if some
8771 * listener gets limited.
8772 */
8773 curproxy->task->expire = TICK_ETERNITY;
8774 } else {
8775 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8776 curproxy->id);
8777 cfgerr++;
8778 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008779 }
8780
Willy Tarreaufbb78422011-06-05 15:38:35 +02008781 /* automatically compute fullconn if not set. We must not do it in the
8782 * loop above because cross-references are not yet fully resolved.
8783 */
8784 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8785 /* If <fullconn> is not set, let's set it to 10% of the sum of
8786 * the possible incoming frontend's maxconns.
8787 */
8788 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8789 struct proxy *fe;
8790 int total = 0;
8791
8792 /* sum up the number of maxconns of frontends which
8793 * reference this backend at least once or which are
8794 * the same one ('listen').
8795 */
8796 for (fe = proxy; fe; fe = fe->next) {
8797 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008798 int found = 0;
8799
8800 if (!(fe->cap & PR_CAP_FE))
8801 continue;
8802
8803 if (fe == curproxy) /* we're on a "listen" instance */
8804 found = 1;
8805
8806 if (fe->defbe.be == curproxy) /* "default_backend" */
8807 found = 1;
8808
8809 /* check if a "use_backend" rule matches */
8810 if (!found) {
8811 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008812 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008813 found = 1;
8814 break;
8815 }
8816 }
8817 }
8818
Willy Tarreaufbb78422011-06-05 15:38:35 +02008819 /* now we've checked all possible ways to reference a backend
8820 * from a frontend.
8821 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008822 if (!found)
8823 continue;
8824 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008825 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008826 /* we have the sum of the maxconns in <total>. We only
8827 * keep 10% of that sum to set the default fullconn, with
8828 * a hard minimum of 1 (to avoid a divide by zero).
8829 */
8830 curproxy->fullconn = (total + 9) / 10;
8831 if (!curproxy->fullconn)
8832 curproxy->fullconn = 1;
8833 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008834 }
8835
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008836 /*
8837 * Recount currently required checks.
8838 */
8839
8840 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8841 int optnum;
8842
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008843 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8844 if (curproxy->options & cfg_opts[optnum].val)
8845 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008846
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008847 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8848 if (curproxy->options2 & cfg_opts2[optnum].val)
8849 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008850 }
8851
Willy Tarreau0fca4832015-05-01 19:12:05 +02008852 /* compute the required process bindings for the peers */
8853 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8854 if (curproxy->table.peers.p)
8855 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8856
Willy Tarreau122541c2011-09-07 21:24:49 +02008857 if (peers) {
8858 struct peers *curpeers = peers, **last;
8859 struct peer *p, *pb;
8860
Willy Tarreau1e273012015-05-01 19:15:17 +02008861 /* Remove all peers sections which don't have a valid listener,
8862 * which are not used by any table, or which are bound to more
8863 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008864 */
8865 last = &peers;
8866 while (*last) {
8867 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008868
8869 if (curpeers->state == PR_STSTOPPED) {
8870 /* the "disabled" keyword was present */
8871 if (curpeers->peers_fe)
8872 stop_proxy(curpeers->peers_fe);
8873 curpeers->peers_fe = NULL;
8874 }
8875 else if (!curpeers->peers_fe) {
8876 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8877 curpeers->id, localpeer);
8878 }
David Carliere6c39412015-07-02 07:00:17 +00008879 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008880 /* either it's totally stopped or too much used */
8881 if (curpeers->peers_fe->bind_proc) {
8882 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008883 "running in different processes (%d different ones). "
8884 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008885 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008886 cfgerr++;
8887 }
8888 stop_proxy(curpeers->peers_fe);
8889 curpeers->peers_fe = NULL;
8890 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008891 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008892 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008893 last = &curpeers->next;
8894 continue;
8895 }
8896
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008897 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008898 p = curpeers->remote;
8899 while (p) {
8900 pb = p->next;
8901 free(p->id);
8902 free(p);
8903 p = pb;
8904 }
8905
8906 /* Destroy and unlink this curpeers section.
8907 * Note: curpeers is backed up into *last.
8908 */
8909 free(curpeers->id);
8910 curpeers = curpeers->next;
8911 free(*last);
8912 *last = curpeers;
8913 }
8914 }
8915
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008916 /* initialize stick-tables on backend capable proxies. This must not
8917 * be done earlier because the data size may be discovered while parsing
8918 * other proxies.
8919 */
8920 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8921 if (curproxy->state == PR_STSTOPPED)
8922 continue;
8923
8924 if (!stktable_init(&curproxy->table)) {
8925 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8926 cfgerr++;
8927 }
8928 }
8929
Simon Horman0d16a402015-01-30 11:22:58 +09008930 if (mailers) {
8931 struct mailers *curmailers = mailers, **last;
8932 struct mailer *m, *mb;
8933
8934 /* Remove all mailers sections which don't have a valid listener.
8935 * This can happen when a mailers section is never referenced.
8936 */
8937 last = &mailers;
8938 while (*last) {
8939 curmailers = *last;
8940 if (curmailers->users) {
8941 last = &curmailers->next;
8942 continue;
8943 }
8944
8945 Warning("Removing incomplete section 'mailers %s'.\n",
8946 curmailers->id);
8947
8948 m = curmailers->mailer_list;
8949 while (m) {
8950 mb = m->next;
8951 free(m->id);
8952 free(m);
8953 m = mb;
8954 }
8955
8956 /* Destroy and unlink this curmailers section.
8957 * Note: curmailers is backed up into *last.
8958 */
8959 free(curmailers->id);
8960 curmailers = curmailers->next;
8961 free(*last);
8962 *last = curmailers;
8963 }
8964 }
8965
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008966 /* Update server_state_file_name to backend name if backend is supposed to use
8967 * a server-state file locally defined and none has been provided */
8968 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8969 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
8970 curproxy->server_state_file_name == NULL)
8971 curproxy->server_state_file_name = strdup(curproxy->id);
8972 }
8973
Willy Tarreau34eb6712011-10-24 18:15:04 +02008974 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008975 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008976 MEM_F_SHARED);
8977
Willy Tarreaubb925012009-07-23 13:36:36 +02008978 if (cfgerr > 0)
8979 err_code |= ERR_ALERT | ERR_FATAL;
8980 out:
8981 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008982}
8983
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008984/*
8985 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8986 * parsing sessions.
8987 */
8988void cfg_register_keywords(struct cfg_kw_list *kwl)
8989{
8990 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8991}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008992
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008993/*
8994 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8995 */
8996void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8997{
8998 LIST_DEL(&kwl->list);
8999 LIST_INIT(&kwl->list);
9000}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009001
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009002/* this function register new section in the haproxy configuration file.
9003 * <section_name> is the name of this new section and <section_parser>
9004 * is the called parser. If two section declaration have the same name,
9005 * only the first declared is used.
9006 */
9007int cfg_register_section(char *section_name,
9008 int (*section_parser)(const char *, int, char **, int))
9009{
9010 struct cfg_section *cs;
9011
9012 cs = calloc(1, sizeof(*cs));
9013 if (!cs) {
9014 Alert("register section '%s': out of memory.\n", section_name);
9015 return 0;
9016 }
9017
9018 cs->section_name = section_name;
9019 cs->section_parser = section_parser;
9020
9021 LIST_ADDQ(&sections, &cs->list);
9022
9023 return 1;
9024}
9025
Willy Tarreaubaaee002006-06-26 02:48:02 +02009026/*
David Carlier845efb52015-09-25 11:49:18 +01009027 * free all config section entries
9028 */
9029void cfg_unregister_sections(void)
9030{
9031 struct cfg_section *cs, *ics;
9032
9033 list_for_each_entry_safe(cs, ics, &sections, list) {
9034 LIST_DEL(&cs->list);
9035 free(cs);
9036 }
9037}
9038
9039/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009040 * Local variables:
9041 * c-indent-level: 8
9042 * c-basic-offset: 8
9043 * End:
9044 */