blob: d343f0515310b117201e5c490586a3937080c967 [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 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006539 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006540 struct cfg_kw_list *kwl;
6541 int index;
6542
6543 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6544 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6545 if (kwl->kw[index].section != CFG_LISTEN)
6546 continue;
6547 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6548 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006549 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006550 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006551 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006552 err_code |= ERR_ALERT | ERR_FATAL;
6553 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006554 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006555 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006556 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006557 err_code |= ERR_WARN;
6558 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006559 }
Willy Tarreau93893792009-07-23 13:19:11 +02006560 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006561 }
6562 }
6563 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006564
Willy Tarreau6daf3432008-01-22 16:44:08 +01006565 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006566 err_code |= ERR_ALERT | ERR_FATAL;
6567 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006568 }
Willy Tarreau93893792009-07-23 13:19:11 +02006569 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006570 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006571 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006572}
6573
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006574int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006575cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6576{
6577#ifdef CONFIG_HAP_NS
6578 const char *err;
6579 const char *item = args[0];
6580
6581 if (!strcmp(item, "namespace_list")) {
6582 return 0;
6583 }
6584 else if (!strcmp(item, "namespace")) {
6585 size_t idx = 1;
6586 const char *current;
6587 while (*(current = args[idx++])) {
6588 err = invalid_char(current);
6589 if (err) {
6590 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6591 file, linenum, *err, item, current);
6592 return ERR_ALERT | ERR_FATAL;
6593 }
6594
6595 if (netns_store_lookup(current, strlen(current))) {
6596 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6597 file, linenum, current);
6598 return ERR_ALERT | ERR_FATAL;
6599 }
6600 if (!netns_store_insert(current)) {
6601 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6602 file, linenum, current);
6603 return ERR_ALERT | ERR_FATAL;
6604 }
6605 }
6606 }
6607
6608 return 0;
6609#else
6610 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6611 file, linenum);
6612 return ERR_ALERT | ERR_FATAL;
6613#endif
6614}
6615
6616int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006617cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6618{
6619
6620 int err_code = 0;
6621 const char *err;
6622
6623 if (!strcmp(args[0], "userlist")) { /* new userlist */
6624 struct userlist *newul;
6625
6626 if (!*args[1]) {
6627 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6628 file, linenum, args[0]);
6629 err_code |= ERR_ALERT | ERR_FATAL;
6630 goto out;
6631 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006632 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6633 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006634
6635 err = invalid_char(args[1]);
6636 if (err) {
6637 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6638 file, linenum, *err, args[0], args[1]);
6639 err_code |= ERR_ALERT | ERR_FATAL;
6640 goto out;
6641 }
6642
6643 for (newul = userlist; newul; newul = newul->next)
6644 if (!strcmp(newul->name, args[1])) {
6645 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6646 file, linenum, args[1]);
6647 err_code |= ERR_WARN;
6648 goto out;
6649 }
6650
6651 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6652 if (!newul) {
6653 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6654 err_code |= ERR_ALERT | ERR_ABORT;
6655 goto out;
6656 }
6657
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006658 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006659 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006660 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6661 err_code |= ERR_ALERT | ERR_ABORT;
6662 goto out;
6663 }
6664
6665 newul->next = userlist;
6666 userlist = newul;
6667
6668 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006669 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006670 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006671 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006672
6673 if (!*args[1]) {
6674 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6675 file, linenum, args[0]);
6676 err_code |= ERR_ALERT | ERR_FATAL;
6677 goto out;
6678 }
6679
6680 err = invalid_char(args[1]);
6681 if (err) {
6682 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6683 file, linenum, *err, args[0], args[1]);
6684 err_code |= ERR_ALERT | ERR_FATAL;
6685 goto out;
6686 }
6687
William Lallemand4ac9f542015-05-28 18:03:51 +02006688 if (!userlist)
6689 goto out;
6690
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006691 for (ag = userlist->groups; ag; ag = ag->next)
6692 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006693 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6694 file, linenum, args[1], userlist->name);
6695 err_code |= ERR_ALERT;
6696 goto out;
6697 }
6698
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006699 ag = calloc(1, sizeof(*ag));
6700 if (!ag) {
6701 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6702 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006703 goto out;
6704 }
6705
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006706 ag->name = strdup(args[1]);
6707 if (!ag) {
6708 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6709 err_code |= ERR_ALERT | ERR_ABORT;
6710 goto out;
6711 }
6712
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006713 cur_arg = 2;
6714
6715 while (*args[cur_arg]) {
6716 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006717 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006718 cur_arg += 2;
6719 continue;
6720 } else {
6721 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6722 file, linenum, args[0]);
6723 err_code |= ERR_ALERT | ERR_FATAL;
6724 goto out;
6725 }
6726 }
6727
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006728 ag->next = userlist->groups;
6729 userlist->groups = ag;
6730
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006731 } else if (!strcmp(args[0], "user")) { /* new user */
6732 struct auth_users *newuser;
6733 int cur_arg;
6734
6735 if (!*args[1]) {
6736 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6737 file, linenum, args[0]);
6738 err_code |= ERR_ALERT | ERR_FATAL;
6739 goto out;
6740 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006741 if (!userlist)
6742 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006743
6744 for (newuser = userlist->users; newuser; newuser = newuser->next)
6745 if (!strcmp(newuser->user, args[1])) {
6746 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6747 file, linenum, args[1], userlist->name);
6748 err_code |= ERR_ALERT;
6749 goto out;
6750 }
6751
6752 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6753 if (!newuser) {
6754 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6755 err_code |= ERR_ALERT | ERR_ABORT;
6756 goto out;
6757 }
6758
6759 newuser->user = strdup(args[1]);
6760
6761 newuser->next = userlist->users;
6762 userlist->users = newuser;
6763
6764 cur_arg = 2;
6765
6766 while (*args[cur_arg]) {
6767 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006768#ifdef CONFIG_HAP_CRYPT
6769 if (!crypt("", args[cur_arg + 1])) {
6770 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6771 file, linenum, newuser->user);
6772 err_code |= ERR_ALERT | ERR_FATAL;
6773 goto out;
6774 }
6775#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006776 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6777 file, linenum);
6778 err_code |= ERR_ALERT;
6779#endif
6780 newuser->pass = strdup(args[cur_arg + 1]);
6781 cur_arg += 2;
6782 continue;
6783 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6784 newuser->pass = strdup(args[cur_arg + 1]);
6785 newuser->flags |= AU_O_INSECURE;
6786 cur_arg += 2;
6787 continue;
6788 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006789 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006790 cur_arg += 2;
6791 continue;
6792 } else {
6793 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6794 file, linenum, args[0]);
6795 err_code |= ERR_ALERT | ERR_FATAL;
6796 goto out;
6797 }
6798 }
6799 } else {
6800 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6801 err_code |= ERR_ALERT | ERR_FATAL;
6802 }
6803
6804out:
6805 return err_code;
6806}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006807
6808/*
6809 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006810 * Returns the error code, 0 if OK, or any combination of :
6811 * - ERR_ABORT: must abort ASAP
6812 * - ERR_FATAL: we can continue parsing but not start the service
6813 * - ERR_WARN: a warning has been emitted
6814 * - ERR_ALERT: an alert has been emitted
6815 * Only the two first ones can stop processing, the two others are just
6816 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006817 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006818int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006819{
William Lallemand64e84512015-05-12 14:25:37 +02006820 char *thisline;
6821 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006822 FILE *f;
6823 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006824 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006825 struct cfg_section *cs = NULL;
6826 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006827 int readbytes = 0;
6828
6829 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006830 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006831 return -1;
6832 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006833
6834 /* Register internal sections */
6835 if (!cfg_register_section("listen", cfg_parse_listen) ||
6836 !cfg_register_section("frontend", cfg_parse_listen) ||
6837 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006838 !cfg_register_section("defaults", cfg_parse_listen) ||
6839 !cfg_register_section("global", cfg_parse_global) ||
6840 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006841 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006842 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006843 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6844 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006845 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006846
Willy Tarreaubaaee002006-06-26 02:48:02 +02006847 if ((f=fopen(file,"r")) == NULL)
6848 return -1;
6849
William Lallemandb2f07452015-05-12 14:27:13 +02006850next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006851 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006852 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006853 char *end;
6854 char *args[MAX_LINE_ARGS + 1];
6855 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006856 int dquote = 0; /* double quote */
6857 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006858
Willy Tarreaubaaee002006-06-26 02:48:02 +02006859 linenum++;
6860
6861 end = line + strlen(line);
6862
William Lallemand64e84512015-05-12 14:25:37 +02006863 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006864 /* Check if we reached the limit and the last char is not \n.
6865 * Watch out for the last line without the terminating '\n'!
6866 */
William Lallemand64e84512015-05-12 14:25:37 +02006867 char *newline;
6868 int newlinesize = linesize * 2;
6869
6870 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6871 if (newline == NULL) {
6872 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6873 file, linenum);
6874 err_code |= ERR_ALERT | ERR_FATAL;
6875 continue;
6876 }
6877
6878 readbytes = linesize - 1;
6879 linesize = newlinesize;
6880 thisline = newline;
6881 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006882 }
6883
William Lallemand64e84512015-05-12 14:25:37 +02006884 readbytes = 0;
6885
Willy Tarreaubaaee002006-06-26 02:48:02 +02006886 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006887 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006888 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006889
Willy Tarreaubaaee002006-06-26 02:48:02 +02006890 arg = 0;
6891 args[arg] = line;
6892
6893 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006894 if (*line == '"' && !squote) { /* double quote outside single quotes */
6895 if (dquote)
6896 dquote = 0;
6897 else
6898 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006899 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006900 end--;
6901 }
6902 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6903 if (squote)
6904 squote = 0;
6905 else
6906 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006907 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006908 end--;
6909 }
6910 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006911 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6912 * C equivalent value. Other combinations left unchanged (eg: \1).
6913 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006914 int skip = 0;
6915 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6916 *line = line[1];
6917 skip = 1;
6918 }
6919 else if (line[1] == 'r') {
6920 *line = '\r';
6921 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006922 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006923 else if (line[1] == 'n') {
6924 *line = '\n';
6925 skip = 1;
6926 }
6927 else if (line[1] == 't') {
6928 *line = '\t';
6929 skip = 1;
6930 }
6931 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006932 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006933 unsigned char hex1, hex2;
6934 hex1 = toupper(line[2]) - '0';
6935 hex2 = toupper(line[3]) - '0';
6936 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6937 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6938 *line = (hex1<<4) + hex2;
6939 skip = 3;
6940 }
6941 else {
6942 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006943 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006944 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006945 } else if (line[1] == '"') {
6946 *line = '"';
6947 skip = 1;
6948 } else if (line[1] == '\'') {
6949 *line = '\'';
6950 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006951 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6952 *line = '$';
6953 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006954 }
6955 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006956 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006957 end -= skip;
6958 }
6959 line++;
6960 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006961 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006962 /* end of string, end of loop */
6963 *line = 0;
6964 break;
6965 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006966 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006967 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006968 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006969 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006970 line++;
6971 args[++arg] = line;
6972 }
William Lallemandb2f07452015-05-12 14:27:13 +02006973 else if (dquote && *line == '$') {
6974 /* environment variables are evaluated inside double quotes */
6975 char *var_beg;
6976 char *var_end;
6977 char save_char;
6978 char *value;
6979 int val_len;
6980 int newlinesize;
6981 int braces = 0;
6982
6983 var_beg = line + 1;
6984 var_end = var_beg;
6985
6986 if (*var_beg == '{') {
6987 var_beg++;
6988 var_end++;
6989 braces = 1;
6990 }
6991
6992 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6993 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6994 err_code |= ERR_ALERT | ERR_FATAL;
6995 goto next_line; /* skip current line */
6996 }
6997
6998 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6999 var_end++;
7000
7001 save_char = *var_end;
7002 *var_end = '\0';
7003 value = getenv(var_beg);
7004 *var_end = save_char;
7005 val_len = value ? strlen(value) : 0;
7006
7007 if (braces) {
7008 if (*var_end == '}') {
7009 var_end++;
7010 braces = 0;
7011 } else {
7012 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7013 err_code |= ERR_ALERT | ERR_FATAL;
7014 goto next_line; /* skip current line */
7015 }
7016 }
7017
7018 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7019
7020 /* if not enough space in thisline */
7021 if (newlinesize > linesize) {
7022 char *newline;
7023
7024 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7025 if (newline == NULL) {
7026 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7027 err_code |= ERR_ALERT | ERR_FATAL;
7028 goto next_line; /* slip current line */
7029 }
7030 /* recompute pointers if realloc returns a new pointer */
7031 if (newline != thisline) {
7032 int i;
7033 int diff;
7034
7035 for (i = 0; i <= arg; i++) {
7036 diff = args[i] - thisline;
7037 args[i] = newline + diff;
7038 }
7039
7040 diff = var_end - thisline;
7041 var_end = newline + diff;
7042 diff = end - thisline;
7043 end = newline + diff;
7044 diff = line - thisline;
7045 line = newline + diff;
7046 thisline = newline;
7047 }
7048 linesize = newlinesize;
7049 }
7050
7051 /* insert value inside the line */
7052 memmove(line + val_len, var_end, end - var_end + 1);
7053 memcpy(line, value, val_len);
7054 end += val_len - (var_end - line);
7055 line += val_len;
7056 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007057 else {
7058 line++;
7059 }
7060 }
William Lallemandb2f07452015-05-12 14:27:13 +02007061
William Lallemandf9873ba2015-05-05 17:37:14 +02007062 if (dquote) {
7063 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7064 err_code |= ERR_ALERT | ERR_FATAL;
7065 }
7066
7067 if (squote) {
7068 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7069 err_code |= ERR_ALERT | ERR_FATAL;
7070 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007071
7072 /* empty line */
7073 if (!**args)
7074 continue;
7075
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007076 if (*line) {
7077 /* we had to stop due to too many args.
7078 * Let's terminate the string, print the offending part then cut the
7079 * last arg.
7080 */
7081 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7082 line++;
7083 *line = '\0';
7084
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007085 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007086 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007087 err_code |= ERR_ALERT | ERR_FATAL;
7088 args[arg] = line;
7089 }
7090
Willy Tarreau540abe42007-05-02 20:50:16 +02007091 /* zero out remaining args and ensure that at least one entry
7092 * is zeroed out.
7093 */
7094 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007095 args[arg] = line;
7096 }
7097
Willy Tarreau3842f002009-06-14 11:39:52 +02007098 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007099 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007100 char *tmp;
7101
Willy Tarreau3842f002009-06-14 11:39:52 +02007102 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007103 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007104 for (arg=0; *args[arg+1]; arg++)
7105 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007106 *tmp = '\0'; // fix the next arg to \0
7107 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007108 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007109 else if (!strcmp(args[0], "default")) {
7110 kwm = KWM_DEF;
7111 for (arg=0; *args[arg+1]; arg++)
7112 args[arg] = args[arg+1]; // shift args after inversion
7113 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007114
William Lallemand0f99e342011-10-12 17:50:54 +02007115 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7116 strcmp(args[0], "log") != 0) {
7117 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007118 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007119 }
7120
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007121 /* detect section start */
7122 list_for_each_entry(ics, &sections, list) {
7123 if (strcmp(args[0], ics->section_name) == 0) {
7124 cursection = ics->section_name;
7125 cs = ics;
7126 break;
7127 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007128 }
7129
Willy Tarreaubaaee002006-06-26 02:48:02 +02007130 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007131 if (cs)
7132 err_code |= cs->section_parser(file, linenum, args, kwm);
7133 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007134 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007135 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007136 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007137
7138 if (err_code & ERR_ABORT)
7139 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007140 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007141 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007142 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007143 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007144 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007145}
7146
Willy Tarreau64ab6072014-09-16 12:17:36 +02007147/* This function propagates processes from frontend <from> to backend <to> so
7148 * that it is always guaranteed that a backend pointed to by a frontend is
7149 * bound to all of its processes. After that, if the target is a "listen"
7150 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007151 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007152 * checked first to ensure that <to> is already bound to all processes of
7153 * <from>, there is no risk of looping and we ensure to follow the shortest
7154 * path to the destination.
7155 *
7156 * It is possible to set <to> to NULL for the first call so that the function
7157 * takes care of visiting the initial frontend in <from>.
7158 *
7159 * It is important to note that the function relies on the fact that all names
7160 * have already been resolved.
7161 */
7162void propagate_processes(struct proxy *from, struct proxy *to)
7163{
7164 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007165
7166 if (to) {
7167 /* check whether we need to go down */
7168 if (from->bind_proc &&
7169 (from->bind_proc & to->bind_proc) == from->bind_proc)
7170 return;
7171
7172 if (!from->bind_proc && !to->bind_proc)
7173 return;
7174
7175 to->bind_proc = from->bind_proc ?
7176 (to->bind_proc | from->bind_proc) : 0;
7177
7178 /* now propagate down */
7179 from = to;
7180 }
7181
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007182 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007183 return;
7184
Willy Tarreauf6b70012014-12-18 14:00:43 +01007185 if (from->state == PR_STSTOPPED)
7186 return;
7187
Willy Tarreau64ab6072014-09-16 12:17:36 +02007188 /* default_backend */
7189 if (from->defbe.be)
7190 propagate_processes(from, from->defbe.be);
7191
7192 /* use_backend */
7193 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007194 if (rule->dynamic)
7195 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007196 to = rule->be.backend;
7197 propagate_processes(from, to);
7198 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007199}
7200
Willy Tarreaubb925012009-07-23 13:36:36 +02007201/*
7202 * Returns the error code, 0 if OK, or any combination of :
7203 * - ERR_ABORT: must abort ASAP
7204 * - ERR_FATAL: we can continue parsing but not start the service
7205 * - ERR_WARN: a warning has been emitted
7206 * - ERR_ALERT: an alert has been emitted
7207 * Only the two first ones can stop processing, the two others are just
7208 * indicators.
7209 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007210int check_config_validity()
7211{
7212 int cfgerr = 0;
7213 struct proxy *curproxy = NULL;
7214 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007215 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007216 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007217 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007218
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007219 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007220 /*
7221 * Now, check for the integrity of all that we have collected.
7222 */
7223
7224 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007225 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007226
Willy Tarreau193b8c62012-11-22 00:17:38 +01007227 if (!global.tune.max_http_hdr)
7228 global.tune.max_http_hdr = MAX_HTTP_HDR;
7229
7230 if (!global.tune.cookie_len)
7231 global.tune.cookie_len = CAPTURE_LEN;
7232
7233 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7234
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007235 /* Post initialisation of the users and groups lists. */
7236 err_code = userlist_postinit();
7237 if (err_code != ERR_NONE)
7238 goto out;
7239
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007240 /* first, we will invert the proxy list order */
7241 curproxy = NULL;
7242 while (proxy) {
7243 struct proxy *next;
7244
7245 next = proxy->next;
7246 proxy->next = curproxy;
7247 curproxy = proxy;
7248 if (!next)
7249 break;
7250 proxy = next;
7251 }
7252
Willy Tarreau419ead82014-09-16 13:41:21 +02007253 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007254 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007255 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007256 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007257 struct act_rule *trule;
7258 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007259 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007260 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007261 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007262
Willy Tarreau050536d2012-10-04 08:47:34 +02007263 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007264 /* proxy ID not set, use automatic numbering with first
7265 * spare entry starting with next_pxid.
7266 */
7267 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7268 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7269 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007270 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007271 next_pxid++;
7272
Willy Tarreau55ea7572007-06-17 19:56:27 +02007273
Willy Tarreaubaaee002006-06-26 02:48:02 +02007274 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007275 /* ensure we don't keep listeners uselessly bound */
7276 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007277 free((void *)curproxy->table.peers.name);
7278 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007279 continue;
7280 }
7281
Willy Tarreau102df612014-05-07 23:56:38 +02007282 /* Check multi-process mode compatibility for the current proxy */
7283
7284 if (curproxy->bind_proc) {
7285 /* an explicit bind-process was specified, let's check how many
7286 * processes remain.
7287 */
David Carliere6c39412015-07-02 07:00:17 +00007288 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007289
7290 curproxy->bind_proc &= nbits(global.nbproc);
7291 if (!curproxy->bind_proc && nbproc == 1) {
7292 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);
7293 curproxy->bind_proc = 1;
7294 }
7295 else if (!curproxy->bind_proc && nbproc > 1) {
7296 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);
7297 curproxy->bind_proc = 0;
7298 }
7299 }
7300
Willy Tarreau3d209582014-05-09 17:06:11 +02007301 /* check and reduce the bind-proc of each listener */
7302 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7303 unsigned long mask;
7304
7305 if (!bind_conf->bind_proc)
7306 continue;
7307
7308 mask = nbits(global.nbproc);
7309 if (curproxy->bind_proc)
7310 mask &= curproxy->bind_proc;
7311 /* mask cannot be null here thanks to the previous checks */
7312
David Carliere6c39412015-07-02 07:00:17 +00007313 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007314 bind_conf->bind_proc &= mask;
7315
7316 if (!bind_conf->bind_proc && nbproc == 1) {
7317 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",
7318 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7319 bind_conf->bind_proc = mask & ~(mask - 1);
7320 }
7321 else if (!bind_conf->bind_proc && nbproc > 1) {
7322 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",
7323 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7324 bind_conf->bind_proc = 0;
7325 }
7326 }
7327
Willy Tarreauff01a212009-03-15 13:46:16 +01007328 switch (curproxy->mode) {
7329 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007330 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007331 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007332 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7333 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007334 cfgerr++;
7335 }
7336
7337 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007338 Warning("config : servers will be ignored for %s '%s'.\n",
7339 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007340 break;
7341
7342 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007343 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007344 break;
7345
7346 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007347 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007348 break;
7349 }
7350
Willy Tarreauf3934b82015-08-11 11:36:45 +02007351 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7352 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7353 proxy_type_str(curproxy), curproxy->id);
7354 err_code |= ERR_WARN;
7355 }
7356
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007357 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007358 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007359 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007360 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7361 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007362 cfgerr++;
7363 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007364#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007365 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007366 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7367 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007368 cfgerr++;
7369 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007370#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007371 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007372 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7373 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007374 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007375 }
7376 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007377 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007378 /* If no LB algo is set in a backend, and we're not in
7379 * transparent mode, dispatch mode nor proxy mode, we
7380 * want to use balance roundrobin by default.
7381 */
7382 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7383 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007384 }
7385 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007386
Willy Tarreau1620ec32011-08-06 17:05:02 +02007387 if (curproxy->options & PR_O_DISPATCH)
7388 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7389 else if (curproxy->options & PR_O_HTTP_PROXY)
7390 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7391 else if (curproxy->options & PR_O_TRANSP)
7392 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007393
Willy Tarreau1620ec32011-08-06 17:05:02 +02007394 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7395 if (curproxy->options & PR_O_DISABLE404) {
7396 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7397 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7398 err_code |= ERR_WARN;
7399 curproxy->options &= ~PR_O_DISABLE404;
7400 }
7401 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7402 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7403 "send-state", proxy_type_str(curproxy), curproxy->id);
7404 err_code |= ERR_WARN;
7405 curproxy->options &= ~PR_O2_CHK_SNDST;
7406 }
Willy Tarreauef781042010-01-27 11:53:01 +01007407 }
7408
Simon Horman98637e52014-06-20 12:30:16 +09007409 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7410 if (!global.external_check) {
7411 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7412 curproxy->id, "option external-check");
7413 cfgerr++;
7414 }
7415 if (!curproxy->check_command) {
7416 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7417 curproxy->id, "option external-check");
7418 cfgerr++;
7419 }
7420 }
7421
Simon Horman64e34162015-02-06 11:11:57 +09007422 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007423 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7424 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007425 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7426 "'email-alert myhostname', or 'email-alert to' "
7427 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007428 "to be present).\n",
7429 proxy_type_str(curproxy), curproxy->id);
7430 err_code |= ERR_WARN;
7431 free_email_alert(curproxy);
7432 }
7433 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007434 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007435 }
7436
Simon Horman98637e52014-06-20 12:30:16 +09007437 if (curproxy->check_command) {
7438 int clear = 0;
7439 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7440 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7441 "external-check command", proxy_type_str(curproxy), curproxy->id);
7442 err_code |= ERR_WARN;
7443 clear = 1;
7444 }
7445 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007446 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007447 curproxy->id, "external-check command");
7448 cfgerr++;
7449 }
7450 if (clear) {
7451 free(curproxy->check_command);
7452 curproxy->check_command = NULL;
7453 }
7454 }
7455
7456 if (curproxy->check_path) {
7457 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7458 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7459 "external-check path", proxy_type_str(curproxy), curproxy->id);
7460 err_code |= ERR_WARN;
7461 free(curproxy->check_path);
7462 curproxy->check_path = NULL;
7463 }
7464 }
7465
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007466 /* if a default backend was specified, let's find it */
7467 if (curproxy->defbe.name) {
7468 struct proxy *target;
7469
Willy Tarreauafb39922015-05-26 12:04:09 +02007470 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007471 if (!target) {
7472 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7473 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007474 cfgerr++;
7475 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007476 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7477 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007478 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007479 } else if (target->mode != curproxy->mode &&
7480 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7481
7482 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7483 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7484 curproxy->conf.file, curproxy->conf.line,
7485 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7486 target->conf.file, target->conf.line);
7487 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007488 } else {
7489 free(curproxy->defbe.name);
7490 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007491
7492 /* Emit a warning if this proxy also has some servers */
7493 if (curproxy->srv) {
7494 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7495 curproxy->id);
7496 err_code |= ERR_WARN;
7497 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007498 }
7499 }
7500
Willy Tarreau55ea7572007-06-17 19:56:27 +02007501 /* find the target proxy for 'use_backend' rules */
7502 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007503 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007504 struct logformat_node *node;
7505 char *pxname;
7506
7507 /* Try to parse the string as a log format expression. If the result
7508 * of the parsing is only one entry containing a simple string, then
7509 * it's a standard string corresponding to a static rule, thus the
7510 * parsing is cancelled and be.name is restored to be resolved.
7511 */
7512 pxname = rule->be.name;
7513 LIST_INIT(&rule->be.expr);
7514 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7515 curproxy->conf.args.file, curproxy->conf.args.line);
7516 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7517
7518 if (!LIST_ISEMPTY(&rule->be.expr)) {
7519 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7520 rule->dynamic = 1;
7521 free(pxname);
7522 continue;
7523 }
7524 /* simple string: free the expression and fall back to static rule */
7525 free(node->arg);
7526 free(node);
7527 }
7528
7529 rule->dynamic = 0;
7530 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007531
Willy Tarreauafb39922015-05-26 12:04:09 +02007532 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007533 if (!target) {
7534 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7535 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007536 cfgerr++;
7537 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007538 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7539 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007540 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007541 } else if (target->mode != curproxy->mode &&
7542 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7543
7544 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7545 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7546 curproxy->conf.file, curproxy->conf.line,
7547 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7548 target->conf.file, target->conf.line);
7549 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007550 } else {
7551 free((void *)rule->be.name);
7552 rule->be.backend = target;
7553 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007554 }
7555
Willy Tarreau64ab6072014-09-16 12:17:36 +02007556 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007557 list_for_each_entry(srule, &curproxy->server_rules, list) {
7558 struct server *target = findserver(curproxy, srule->srv.name);
7559
7560 if (!target) {
7561 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7562 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7563 cfgerr++;
7564 continue;
7565 }
7566 free((void *)srule->srv.name);
7567 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007568 }
7569
Emeric Brunb982a3d2010-01-04 15:45:53 +01007570 /* find the target table for 'stick' rules */
7571 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7572 struct proxy *target;
7573
Emeric Brun1d33b292010-01-04 15:47:17 +01007574 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7575 if (mrule->flags & STK_IS_STORE)
7576 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7577
Emeric Brunb982a3d2010-01-04 15:45:53 +01007578 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007579 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007580 else
7581 target = curproxy;
7582
7583 if (!target) {
7584 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7585 curproxy->id, mrule->table.name);
7586 cfgerr++;
7587 }
7588 else if (target->table.size == 0) {
7589 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7590 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7591 cfgerr++;
7592 }
Willy Tarreau12785782012-04-27 21:37:17 +02007593 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7594 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007595 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7596 cfgerr++;
7597 }
7598 else {
7599 free((void *)mrule->table.name);
7600 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007601 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007602 }
7603 }
7604
7605 /* find the target table for 'store response' rules */
7606 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7607 struct proxy *target;
7608
Emeric Brun1d33b292010-01-04 15:47:17 +01007609 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7610
Emeric Brunb982a3d2010-01-04 15:45:53 +01007611 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007612 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007613 else
7614 target = curproxy;
7615
7616 if (!target) {
7617 Alert("Proxy '%s': unable to find store table '%s'.\n",
7618 curproxy->id, mrule->table.name);
7619 cfgerr++;
7620 }
7621 else if (target->table.size == 0) {
7622 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7623 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7624 cfgerr++;
7625 }
Willy Tarreau12785782012-04-27 21:37:17 +02007626 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7627 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007628 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7629 cfgerr++;
7630 }
7631 else {
7632 free((void *)mrule->table.name);
7633 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007634 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007635 }
7636 }
7637
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007638 /* find the target table for 'tcp-request' layer 4 rules */
7639 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7640 struct proxy *target;
7641
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007642 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007643 continue;
7644
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007645 if (trule->arg.trk_ctr.table.n)
7646 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007647 else
7648 target = curproxy;
7649
7650 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007651 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007652 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007653 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007654 cfgerr++;
7655 }
7656 else if (target->table.size == 0) {
7657 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007658 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007659 cfgerr++;
7660 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007661 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007662 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007663 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007664 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007665 cfgerr++;
7666 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007667 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007668 free(trule->arg.trk_ctr.table.n);
7669 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007670 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007671 * to pass a list of counters to track and allocate them right here using
7672 * stktable_alloc_data_type().
7673 */
7674 }
7675 }
7676
Willy Tarreaud1f96522010-08-03 19:34:32 +02007677 /* find the target table for 'tcp-request' layer 6 rules */
7678 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7679 struct proxy *target;
7680
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007681 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007682 continue;
7683
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007684 if (trule->arg.trk_ctr.table.n)
7685 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007686 else
7687 target = curproxy;
7688
7689 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007690 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007691 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007692 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007693 cfgerr++;
7694 }
7695 else if (target->table.size == 0) {
7696 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007697 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007698 cfgerr++;
7699 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007700 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007701 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007702 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007703 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007704 cfgerr++;
7705 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007706 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007707 free(trule->arg.trk_ctr.table.n);
7708 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007709 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007710 * to pass a list of counters to track and allocate them right here using
7711 * stktable_alloc_data_type().
7712 */
7713 }
7714 }
7715
Baptiste Assmanne9544932015-11-03 23:31:35 +01007716 /* parse http-request capture rules to ensure id really exists */
7717 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7718 if (hrqrule->action != ACT_CUSTOM ||
7719 hrqrule->action_ptr != http_action_req_capture_by_id)
7720 continue;
7721
7722 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7723 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7724 curproxy->id, hrqrule->arg.capid.idx);
7725 cfgerr++;
7726 }
7727 }
7728
7729 /* parse http-response capture rules to ensure id really exists */
7730 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7731 if (hrqrule->action != ACT_CUSTOM ||
7732 hrqrule->action_ptr != http_action_res_capture_by_id)
7733 continue;
7734
7735 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7736 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7737 curproxy->id, hrqrule->arg.capid.idx);
7738 cfgerr++;
7739 }
7740 }
7741
Willy Tarreau09448f72014-06-25 18:12:15 +02007742 /* find the target table for 'http-request' layer 7 rules */
7743 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7744 struct proxy *target;
7745
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007746 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007747 continue;
7748
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007749 if (hrqrule->arg.trk_ctr.table.n)
7750 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007751 else
7752 target = curproxy;
7753
7754 if (!target) {
7755 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007756 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007757 http_req_trk_idx(hrqrule->action));
7758 cfgerr++;
7759 }
7760 else if (target->table.size == 0) {
7761 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007762 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007763 cfgerr++;
7764 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007765 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007766 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007767 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007768 http_req_trk_idx(hrqrule->action));
7769 cfgerr++;
7770 }
7771 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007772 free(hrqrule->arg.trk_ctr.table.n);
7773 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007774 /* Note: if we decide to enhance the track-sc syntax, we may be able
7775 * to pass a list of counters to track and allocate them right here using
7776 * stktable_alloc_data_type().
7777 */
7778 }
7779 }
7780
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007781 /* move any "block" rules at the beginning of the http-request rules */
7782 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7783 /* insert block_rules into http_req_rules at the beginning */
7784 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7785 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7786 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7787 curproxy->http_req_rules.n = curproxy->block_rules.n;
7788 LIST_INIT(&curproxy->block_rules);
7789 }
7790
Emeric Brun32da3c42010-09-23 18:39:19 +02007791 if (curproxy->table.peers.name) {
7792 struct peers *curpeers = peers;
7793
7794 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7795 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7796 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007797 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007798 break;
7799 }
7800 }
7801
7802 if (!curpeers) {
7803 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7804 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007805 free((void *)curproxy->table.peers.name);
7806 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007807 cfgerr++;
7808 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007809 else if (curpeers->state == PR_STSTOPPED) {
7810 /* silently disable this peers section */
7811 curproxy->table.peers.p = NULL;
7812 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007813 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007814 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7815 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007816 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007817 cfgerr++;
7818 }
7819 }
7820
Simon Horman9dc49962015-01-30 11:22:59 +09007821
7822 if (curproxy->email_alert.mailers.name) {
7823 struct mailers *curmailers = mailers;
7824
7825 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7826 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7827 free(curproxy->email_alert.mailers.name);
7828 curproxy->email_alert.mailers.m = curmailers;
7829 curmailers->users++;
7830 break;
7831 }
7832 }
7833
7834 if (!curmailers) {
7835 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7836 curproxy->id, curproxy->email_alert.mailers.name);
7837 free_email_alert(curproxy);
7838 cfgerr++;
7839 }
7840 }
7841
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007842 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007843 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007844 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7845 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7846 "proxy", curproxy->id);
7847 cfgerr++;
7848 goto out_uri_auth_compat;
7849 }
7850
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007851 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007852 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007853 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007854 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007855
Willy Tarreau95fa4692010-02-01 13:05:50 +01007856 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7857 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007858
7859 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007860 uri_auth_compat_req[i++] = "realm";
7861 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7862 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007863
Willy Tarreau95fa4692010-02-01 13:05:50 +01007864 uri_auth_compat_req[i++] = "unless";
7865 uri_auth_compat_req[i++] = "{";
7866 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7867 uri_auth_compat_req[i++] = "}";
7868 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007869
Willy Tarreauff011f22011-01-06 17:51:27 +01007870 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7871 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007872 cfgerr++;
7873 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007874 }
7875
Willy Tarreauff011f22011-01-06 17:51:27 +01007876 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007877
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007878 if (curproxy->uri_auth->auth_realm) {
7879 free(curproxy->uri_auth->auth_realm);
7880 curproxy->uri_auth->auth_realm = NULL;
7881 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007882
7883 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007884 }
7885out_uri_auth_compat:
7886
Dragan Dosen43885c72015-10-01 13:18:13 +02007887 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02007888 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02007889 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
7890 if (!curproxy->conf.logformat_sd_string) {
7891 /* set the default logformat_sd_string */
7892 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
7893 }
Dragan Dosen1322d092015-09-22 16:05:32 +02007894 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02007895 }
Dragan Dosen1322d092015-09-22 16:05:32 +02007896 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02007897
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007898 /* compile the log format */
7899 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007900 if (curproxy->conf.logformat_string != default_http_log_format &&
7901 curproxy->conf.logformat_string != default_tcp_log_format &&
7902 curproxy->conf.logformat_string != clf_http_log_format)
7903 free(curproxy->conf.logformat_string);
7904 curproxy->conf.logformat_string = NULL;
7905 free(curproxy->conf.lfs_file);
7906 curproxy->conf.lfs_file = NULL;
7907 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007908
7909 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
7910 free(curproxy->conf.logformat_sd_string);
7911 curproxy->conf.logformat_sd_string = NULL;
7912 free(curproxy->conf.lfsd_file);
7913 curproxy->conf.lfsd_file = NULL;
7914 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007915 }
7916
Willy Tarreau62a61232013-04-12 18:13:46 +02007917 if (curproxy->conf.logformat_string) {
7918 curproxy->conf.args.ctx = ARGC_LOG;
7919 curproxy->conf.args.file = curproxy->conf.lfs_file;
7920 curproxy->conf.args.line = curproxy->conf.lfs_line;
7921 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007922 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007923 curproxy->conf.args.file = NULL;
7924 curproxy->conf.args.line = 0;
7925 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007926
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007927 if (curproxy->conf.logformat_sd_string) {
7928 curproxy->conf.args.ctx = ARGC_LOGSD;
7929 curproxy->conf.args.file = curproxy->conf.lfsd_file;
7930 curproxy->conf.args.line = curproxy->conf.lfsd_line;
7931 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
7932 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
7933 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
7934 curproxy->conf.args.file = NULL;
7935 curproxy->conf.args.line = 0;
7936 }
7937
Willy Tarreau62a61232013-04-12 18:13:46 +02007938 if (curproxy->conf.uniqueid_format_string) {
7939 curproxy->conf.args.ctx = ARGC_UIF;
7940 curproxy->conf.args.file = curproxy->conf.uif_file;
7941 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007942 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007943 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007944 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007945 curproxy->conf.args.file = NULL;
7946 curproxy->conf.args.line = 0;
7947 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007948
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007949 /* only now we can check if some args remain unresolved.
7950 * This must be done after the users and groups resolution.
7951 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007952 cfgerr += smp_resolve_args(curproxy);
7953 if (!cfgerr)
7954 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007955
Willy Tarreau2738a142006-07-08 17:28:09 +02007956 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007957 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007958 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007959 (!curproxy->timeout.connect ||
7960 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007961 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007962 " | While not properly invalid, you will certainly encounter various problems\n"
7963 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007964 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007965 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007966 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007967 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007968
Willy Tarreau1fa31262007-12-03 00:36:16 +01007969 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7970 * We must still support older configurations, so let's find out whether those
7971 * parameters have been set or must be copied from contimeouts.
7972 */
7973 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007974 if (!curproxy->timeout.tarpit ||
7975 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007976 /* tarpit timeout not set. We search in the following order:
7977 * default.tarpit, curr.connect, default.connect.
7978 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007979 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007980 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007981 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007982 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007983 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007984 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007985 }
7986 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007987 (!curproxy->timeout.queue ||
7988 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007989 /* queue timeout not set. We search in the following order:
7990 * default.queue, curr.connect, default.connect.
7991 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007992 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007993 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007994 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007995 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007996 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007997 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007998 }
7999 }
8000
Willy Tarreau1620ec32011-08-06 17:05:02 +02008001 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008002 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
8003 curproxy->check_req = (char *)malloc(curproxy->check_len);
8004 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008005 }
8006
Willy Tarreau215663d2014-06-13 18:30:23 +02008007 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8008 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8009 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8010 proxy_type_str(curproxy), curproxy->id);
8011 err_code |= ERR_WARN;
8012 }
8013
Willy Tarreau193b8c62012-11-22 00:17:38 +01008014 /* ensure that cookie capture length is not too large */
8015 if (curproxy->capture_len >= global.tune.cookie_len) {
8016 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8017 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8018 err_code |= ERR_WARN;
8019 curproxy->capture_len = global.tune.cookie_len - 1;
8020 }
8021
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008022 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008023 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008024 curproxy->req_cap_pool = create_pool("ptrcap",
8025 curproxy->nb_req_cap * sizeof(char *),
8026 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008027 }
8028
8029 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008030 curproxy->rsp_cap_pool = create_pool("ptrcap",
8031 curproxy->nb_rsp_cap * sizeof(char *),
8032 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008033 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008034
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008035 switch (curproxy->load_server_state_from_file) {
8036 case PR_SRV_STATE_FILE_UNSPEC:
8037 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8038 break;
8039 case PR_SRV_STATE_FILE_GLOBAL:
8040 if (!global.server_state_file) {
8041 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",
8042 curproxy->id);
8043 err_code |= ERR_WARN;
8044 }
8045 break;
8046 }
8047
Willy Tarreaubaaee002006-06-26 02:48:02 +02008048 /* first, we will invert the servers list order */
8049 newsrv = NULL;
8050 while (curproxy->srv) {
8051 struct server *next;
8052
8053 next = curproxy->srv->next;
8054 curproxy->srv->next = newsrv;
8055 newsrv = curproxy->srv;
8056 if (!next)
8057 break;
8058 curproxy->srv = next;
8059 }
8060
Willy Tarreau17edc812014-01-03 12:14:34 +01008061 /* Check that no server name conflicts. This causes trouble in the stats.
8062 * We only emit a warning for the first conflict affecting each server,
8063 * in order to avoid combinatory explosion if all servers have the same
8064 * name. We do that only for servers which do not have an explicit ID,
8065 * because these IDs were made also for distinguishing them and we don't
8066 * want to annoy people who correctly manage them.
8067 */
8068 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8069 struct server *other_srv;
8070
8071 if (newsrv->puid)
8072 continue;
8073
8074 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8075 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8076 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8077 newsrv->conf.file, newsrv->conf.line,
8078 proxy_type_str(curproxy), curproxy->id,
8079 newsrv->id, other_srv->conf.line);
8080 break;
8081 }
8082 }
8083 }
8084
Willy Tarreaudd701652010-05-25 23:03:02 +02008085 /* assign automatic UIDs to servers which don't have one yet */
8086 next_id = 1;
8087 newsrv = curproxy->srv;
8088 while (newsrv != NULL) {
8089 if (!newsrv->puid) {
8090 /* server ID not set, use automatic numbering with first
8091 * spare entry starting with next_svid.
8092 */
8093 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8094 newsrv->conf.id.key = newsrv->puid = next_id;
8095 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8096 }
8097 next_id++;
8098 newsrv = newsrv->next;
8099 }
8100
Willy Tarreau20697042007-11-15 23:26:18 +01008101 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008102 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008103
Willy Tarreau62c3be22012-01-20 13:12:32 +01008104 /*
8105 * If this server supports a maxconn parameter, it needs a dedicated
8106 * tasks to fill the emptied slots when a connection leaves.
8107 * Also, resolve deferred tracking dependency if needed.
8108 */
8109 newsrv = curproxy->srv;
8110 while (newsrv != NULL) {
8111 if (newsrv->minconn > newsrv->maxconn) {
8112 /* Only 'minconn' was specified, or it was higher than or equal
8113 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8114 * this will avoid further useless expensive computations.
8115 */
8116 newsrv->maxconn = newsrv->minconn;
8117 } else if (newsrv->maxconn && !newsrv->minconn) {
8118 /* minconn was not specified, so we set it to maxconn */
8119 newsrv->minconn = newsrv->maxconn;
8120 }
8121
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008122#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008123 if (newsrv->use_ssl || newsrv->check.use_ssl)
8124 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008125#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008126
Willy Tarreau2f075e92013-12-03 11:11:34 +01008127 /* set the check type on the server */
8128 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8129
Willy Tarreau62c3be22012-01-20 13:12:32 +01008130 if (newsrv->trackit) {
8131 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008132 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008133 char *pname, *sname;
8134
8135 pname = newsrv->trackit;
8136 sname = strrchr(pname, '/');
8137
8138 if (sname)
8139 *sname++ = '\0';
8140 else {
8141 sname = pname;
8142 pname = NULL;
8143 }
8144
8145 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008146 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008147 if (!px) {
8148 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8149 proxy_type_str(curproxy), curproxy->id,
8150 newsrv->id, pname);
8151 cfgerr++;
8152 goto next_srv;
8153 }
8154 } else
8155 px = curproxy;
8156
8157 srv = findserver(px, sname);
8158 if (!srv) {
8159 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8160 proxy_type_str(curproxy), curproxy->id,
8161 newsrv->id, sname);
8162 cfgerr++;
8163 goto next_srv;
8164 }
8165
Willy Tarreau32091232014-05-16 13:52:00 +02008166 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8167 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8168 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008169 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008170 "tracking as it does not have any check nor agent enabled.\n",
8171 proxy_type_str(curproxy), curproxy->id,
8172 newsrv->id, px->id, srv->id);
8173 cfgerr++;
8174 goto next_srv;
8175 }
8176
8177 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8178
8179 if (loop) {
8180 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8181 "belongs to a tracking chain looping back to %s/%s.\n",
8182 proxy_type_str(curproxy), curproxy->id,
8183 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008184 cfgerr++;
8185 goto next_srv;
8186 }
8187
8188 if (curproxy != px &&
8189 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8190 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8191 "tracking: disable-on-404 option inconsistency.\n",
8192 proxy_type_str(curproxy), curproxy->id,
8193 newsrv->id, px->id, srv->id);
8194 cfgerr++;
8195 goto next_srv;
8196 }
8197
8198 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008199 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008200 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008201 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008202 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008203 }
8204
8205 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008206 newsrv->tracknext = srv->trackers;
8207 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008208
8209 free(newsrv->trackit);
8210 newsrv->trackit = NULL;
8211 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008212
8213 /*
8214 * resolve server's resolvers name and update the resolvers pointer
8215 * accordingly
8216 */
8217 if (newsrv->resolvers_id) {
8218 struct dns_resolvers *curr_resolvers;
8219 int found;
8220
8221 found = 0;
8222 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8223 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8224 found = 1;
8225 break;
8226 }
8227 }
8228
8229 if (!found) {
8230 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8231 proxy_type_str(curproxy), curproxy->id,
8232 newsrv->id, newsrv->resolvers_id);
8233 cfgerr++;
8234 } else {
8235 free(newsrv->resolvers_id);
8236 newsrv->resolvers_id = NULL;
8237 if (newsrv->resolution)
8238 newsrv->resolution->resolvers = curr_resolvers;
8239 }
8240 }
8241 else {
8242 /* if no resolvers section associated to this server
8243 * we can clean up the associated resolution structure
8244 */
8245 if (newsrv->resolution) {
8246 free(newsrv->resolution->hostname_dn);
8247 newsrv->resolution->hostname_dn = NULL;
8248 free(newsrv->resolution);
8249 newsrv->resolution = NULL;
8250 }
8251 }
8252
Willy Tarreau62c3be22012-01-20 13:12:32 +01008253 next_srv:
8254 newsrv = newsrv->next;
8255 }
8256
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008257 /* We have to initialize the server lookup mechanism depending
8258 * on what LB algorithm was choosen.
8259 */
8260
8261 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8262 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8263 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008264 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8265 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8266 init_server_map(curproxy);
8267 } else {
8268 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8269 fwrr_init_server_groups(curproxy);
8270 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008271 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008272
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008273 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008274 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8275 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8276 fwlc_init_server_tree(curproxy);
8277 } else {
8278 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8279 fas_init_server_tree(curproxy);
8280 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008281 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008282
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008283 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008284 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8285 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8286 chash_init_server_tree(curproxy);
8287 } else {
8288 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8289 init_server_map(curproxy);
8290 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008291 break;
8292 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008293
8294 if (curproxy->options & PR_O_LOGASAP)
8295 curproxy->to_log &= ~LW_BYTES;
8296
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008297 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008298 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8299 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008300 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8301 proxy_type_str(curproxy), curproxy->id);
8302 err_code |= ERR_WARN;
8303 }
8304
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008305 if (curproxy->mode != PR_MODE_HTTP) {
8306 int optnum;
8307
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008308 if (curproxy->uri_auth) {
8309 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8310 proxy_type_str(curproxy), curproxy->id);
8311 err_code |= ERR_WARN;
8312 curproxy->uri_auth = NULL;
8313 }
8314
Willy Tarreau87cf5142011-08-19 22:57:24 +02008315 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008316 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8317 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8318 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008319 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008320 }
8321
8322 if (curproxy->options & PR_O_ORGTO) {
8323 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8324 "originalto", proxy_type_str(curproxy), curproxy->id);
8325 err_code |= ERR_WARN;
8326 curproxy->options &= ~PR_O_ORGTO;
8327 }
8328
8329 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8330 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8331 (curproxy->cap & cfg_opts[optnum].cap) &&
8332 (curproxy->options & cfg_opts[optnum].val)) {
8333 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8334 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8335 err_code |= ERR_WARN;
8336 curproxy->options &= ~cfg_opts[optnum].val;
8337 }
8338 }
8339
8340 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8341 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8342 (curproxy->cap & cfg_opts2[optnum].cap) &&
8343 (curproxy->options2 & cfg_opts2[optnum].val)) {
8344 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8345 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8346 err_code |= ERR_WARN;
8347 curproxy->options2 &= ~cfg_opts2[optnum].val;
8348 }
8349 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008350
Willy Tarreau29fbe512015-08-20 19:35:14 +02008351#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008352 if (curproxy->conn_src.bind_hdr_occ) {
8353 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008354 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008355 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008356 err_code |= ERR_WARN;
8357 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008358#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008359 }
8360
Willy Tarreaubaaee002006-06-26 02:48:02 +02008361 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008362 * ensure that we're not cross-dressing a TCP server into HTTP.
8363 */
8364 newsrv = curproxy->srv;
8365 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008366 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008367 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8368 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008369 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008370 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008371
Willy Tarreau0cec3312011-10-31 13:49:26 +01008372 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8373 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8374 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8375 err_code |= ERR_WARN;
8376 }
8377
Willy Tarreauc93cd162014-05-13 15:54:22 +02008378 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008379 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8380 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8381 err_code |= ERR_WARN;
8382 }
8383
Willy Tarreau29fbe512015-08-20 19:35:14 +02008384#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008385 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8386 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008387 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 +01008388 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008389 err_code |= ERR_WARN;
8390 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008391#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008392 newsrv = newsrv->next;
8393 }
8394
Willy Tarreaue42bd962014-09-16 16:21:19 +02008395 /* check if we have a frontend with "tcp-request content" looking at L7
8396 * with no inspect-delay
8397 */
8398 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8399 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008400 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008401 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008402 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008403 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008404 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008405 break;
8406 }
8407
8408 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8409 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8410 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8411 " This means that these rules will randomly find their contents. This can be fixed by"
8412 " setting the tcp-request inspect-delay.\n",
8413 proxy_type_str(curproxy), curproxy->id);
8414 err_code |= ERR_WARN;
8415 }
8416 }
8417
Christopher Fauletd7c91962015-04-30 11:48:27 +02008418 /* Check filter configuration, if any */
8419 cfgerr += flt_check(curproxy);
8420
Willy Tarreauc1a21672009-08-16 22:37:44 +02008421 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008422 if (!curproxy->accept)
8423 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008424
Willy Tarreauc1a21672009-08-16 22:37:44 +02008425 if (curproxy->tcp_req.inspect_delay ||
8426 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008427 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008428
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008429 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008430 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008431 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008432 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008433
8434 /* both TCP and HTTP must check switching rules */
8435 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008436
8437 /* Add filters analyzers if needed */
8438 if (!LIST_ISEMPTY(&curproxy->filters)) {
8439 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8440 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
8441 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008442 }
8443
8444 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008445 if (curproxy->tcp_req.inspect_delay ||
8446 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8447 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8448
Emeric Brun97679e72010-09-23 17:56:44 +02008449 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8450 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8451
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008452 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008453 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008454 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008455 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008456
8457 /* If the backend does requires RDP cookie persistence, we have to
8458 * enable the corresponding analyser.
8459 */
8460 if (curproxy->options2 & PR_O2_RDPC_PRST)
8461 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008462
8463 /* Add filters analyzers if needed */
8464 if (!LIST_ISEMPTY(&curproxy->filters)) {
8465 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8466 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
8467 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008468 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008469 }
8470
8471 /***********************************************************/
8472 /* At this point, target names have already been resolved. */
8473 /***********************************************************/
8474
8475 /* Check multi-process mode compatibility */
8476
8477 if (global.nbproc > 1 && global.stats_fe) {
8478 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8479 unsigned long mask;
8480
8481 mask = nbits(global.nbproc);
8482 if (global.stats_fe->bind_proc)
8483 mask &= global.stats_fe->bind_proc;
8484
8485 if (bind_conf->bind_proc)
8486 mask &= bind_conf->bind_proc;
8487
8488 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008489 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008490 break;
8491 }
8492 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8493 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");
8494 }
8495 }
8496
8497 /* Make each frontend inherit bind-process from its listeners when not specified. */
8498 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8499 if (curproxy->bind_proc)
8500 continue;
8501
8502 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8503 unsigned long mask;
8504
Willy Tarreaue428b082015-05-04 21:57:58 +02008505 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008506 curproxy->bind_proc |= mask;
8507 }
8508
8509 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008510 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008511 }
8512
8513 if (global.stats_fe) {
8514 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8515 unsigned long mask;
8516
Willy Tarreaue428b082015-05-04 21:57:58 +02008517 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008518 global.stats_fe->bind_proc |= mask;
8519 }
8520 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008521 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008522 }
8523
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008524 /* propagate bindings from frontends to backends. Don't do it if there
8525 * are any fatal errors as we must not call it with unresolved proxies.
8526 */
8527 if (!cfgerr) {
8528 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8529 if (curproxy->cap & PR_CAP_FE)
8530 propagate_processes(curproxy, NULL);
8531 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008532 }
8533
8534 /* Bind each unbound backend to all processes when not specified. */
8535 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8536 if (curproxy->bind_proc)
8537 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008538 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008539 }
8540
8541 /*******************************************************/
8542 /* At this step, all proxies have a non-null bind_proc */
8543 /*******************************************************/
8544
8545 /* perform the final checks before creating tasks */
8546
8547 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8548 struct listener *listener;
8549 unsigned int next_id;
8550 int nbproc;
8551
David Carliere6c39412015-07-02 07:00:17 +00008552 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008553
Emeric Brunc52962f2012-11-15 18:28:02 +01008554#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008555 /* Configure SSL for each bind line.
8556 * Note: if configuration fails at some point, the ->ctx member
8557 * remains NULL so that listeners can later detach.
8558 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008559 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008560 int alloc_ctx;
8561
Emeric Brunc52962f2012-11-15 18:28:02 +01008562 if (!bind_conf->is_ssl) {
8563 if (bind_conf->default_ctx) {
8564 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8565 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8566 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008567 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008568 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008569 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008570 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008571 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008572 cfgerr++;
8573 continue;
8574 }
8575
Emeric Brun8dc60392014-05-09 13:52:00 +02008576 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008577 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008578 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8579 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");
8580 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008581 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008582 cfgerr++;
8583 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008584 }
8585
Emeric Brunfc0421f2012-09-07 17:30:07 +02008586 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008587 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008588
8589 /* initialize CA variables if the certificates generation is enabled */
8590 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008591 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008592#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008593
Willy Tarreaue6b98942007-10-29 01:09:36 +01008594 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008595 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008596 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008597 if (!listener->luid) {
8598 /* listener ID not set, use automatic numbering with first
8599 * spare entry starting with next_luid.
8600 */
8601 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8602 listener->conf.id.key = listener->luid = next_id;
8603 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008604 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008605 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008606
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008607 /* enable separate counters */
8608 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8609 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008610 if (!listener->name)
8611 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008612 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008613
Willy Tarreaue6b98942007-10-29 01:09:36 +01008614 if (curproxy->options & PR_O_TCP_NOLING)
8615 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008616 if (!listener->maxconn)
8617 listener->maxconn = curproxy->maxconn;
8618 if (!listener->backlog)
8619 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008620 if (!listener->maxaccept)
8621 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8622
8623 /* we want to have an optimal behaviour on single process mode to
8624 * maximize the work at once, but in multi-process we want to keep
8625 * some fairness between processes, so we target half of the max
8626 * number of events to be balanced over all the processes the proxy
8627 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8628 * used to disable the limit.
8629 */
8630 if (listener->maxaccept > 0) {
8631 if (nbproc > 1)
8632 listener->maxaccept = (listener->maxaccept + 1) / 2;
8633 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8634 }
8635
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008636 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008637 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008638 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008639 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008640
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008641 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8642 listener->options |= LI_O_TCP_RULES;
8643
Willy Tarreaude3041d2010-05-31 10:56:17 +02008644 if (curproxy->mon_mask.s_addr)
8645 listener->options |= LI_O_CHK_MONNET;
8646
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008647 /* smart accept mode is automatic in HTTP mode */
8648 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008649 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008650 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8651 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008652 }
8653
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008654 /* Release unused SSL configs */
8655 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8656 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008657 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008658#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008659 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008660 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008661 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008662 free(bind_conf->ca_sign_file);
8663 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008664 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008665 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008666 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008667 if(bind_conf->keys_ref) {
8668 free(bind_conf->keys_ref->filename);
8669 free(bind_conf->keys_ref->tlskeys);
8670 free(bind_conf->keys_ref);
8671 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008672#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008673 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008674
Willy Tarreau102df612014-05-07 23:56:38 +02008675 if (nbproc > 1) {
8676 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008677 int count, maxproc = 0;
8678
8679 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008680 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008681 if (count > maxproc)
8682 maxproc = count;
8683 }
8684 /* backends have 0, frontends have 1 or more */
8685 if (maxproc != 1)
8686 Warning("Proxy '%s': in multi-process mode, stats will be"
8687 " limited to process assigned to the current request.\n",
8688 curproxy->id);
8689
Willy Tarreau102df612014-05-07 23:56:38 +02008690 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8691 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8692 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008693 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008694 }
Willy Tarreau102df612014-05-07 23:56:38 +02008695 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8696 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8697 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008698 }
8699 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008700
8701 /* create the task associated with the proxy */
8702 curproxy->task = task_new();
8703 if (curproxy->task) {
8704 curproxy->task->context = curproxy;
8705 curproxy->task->process = manage_proxy;
8706 /* no need to queue, it will be done automatically if some
8707 * listener gets limited.
8708 */
8709 curproxy->task->expire = TICK_ETERNITY;
8710 } else {
8711 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8712 curproxy->id);
8713 cfgerr++;
8714 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008715 }
8716
Willy Tarreaufbb78422011-06-05 15:38:35 +02008717 /* automatically compute fullconn if not set. We must not do it in the
8718 * loop above because cross-references are not yet fully resolved.
8719 */
8720 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8721 /* If <fullconn> is not set, let's set it to 10% of the sum of
8722 * the possible incoming frontend's maxconns.
8723 */
8724 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8725 struct proxy *fe;
8726 int total = 0;
8727
8728 /* sum up the number of maxconns of frontends which
8729 * reference this backend at least once or which are
8730 * the same one ('listen').
8731 */
8732 for (fe = proxy; fe; fe = fe->next) {
8733 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008734 int found = 0;
8735
8736 if (!(fe->cap & PR_CAP_FE))
8737 continue;
8738
8739 if (fe == curproxy) /* we're on a "listen" instance */
8740 found = 1;
8741
8742 if (fe->defbe.be == curproxy) /* "default_backend" */
8743 found = 1;
8744
8745 /* check if a "use_backend" rule matches */
8746 if (!found) {
8747 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008748 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008749 found = 1;
8750 break;
8751 }
8752 }
8753 }
8754
Willy Tarreaufbb78422011-06-05 15:38:35 +02008755 /* now we've checked all possible ways to reference a backend
8756 * from a frontend.
8757 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008758 if (!found)
8759 continue;
8760 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008761 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008762 /* we have the sum of the maxconns in <total>. We only
8763 * keep 10% of that sum to set the default fullconn, with
8764 * a hard minimum of 1 (to avoid a divide by zero).
8765 */
8766 curproxy->fullconn = (total + 9) / 10;
8767 if (!curproxy->fullconn)
8768 curproxy->fullconn = 1;
8769 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008770 }
8771
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008772 /*
8773 * Recount currently required checks.
8774 */
8775
8776 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8777 int optnum;
8778
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008779 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8780 if (curproxy->options & cfg_opts[optnum].val)
8781 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008782
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008783 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8784 if (curproxy->options2 & cfg_opts2[optnum].val)
8785 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008786 }
8787
Willy Tarreau0fca4832015-05-01 19:12:05 +02008788 /* compute the required process bindings for the peers */
8789 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8790 if (curproxy->table.peers.p)
8791 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8792
Willy Tarreau122541c2011-09-07 21:24:49 +02008793 if (peers) {
8794 struct peers *curpeers = peers, **last;
8795 struct peer *p, *pb;
8796
Willy Tarreau1e273012015-05-01 19:15:17 +02008797 /* Remove all peers sections which don't have a valid listener,
8798 * which are not used by any table, or which are bound to more
8799 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008800 */
8801 last = &peers;
8802 while (*last) {
8803 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008804
8805 if (curpeers->state == PR_STSTOPPED) {
8806 /* the "disabled" keyword was present */
8807 if (curpeers->peers_fe)
8808 stop_proxy(curpeers->peers_fe);
8809 curpeers->peers_fe = NULL;
8810 }
8811 else if (!curpeers->peers_fe) {
8812 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8813 curpeers->id, localpeer);
8814 }
David Carliere6c39412015-07-02 07:00:17 +00008815 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008816 /* either it's totally stopped or too much used */
8817 if (curpeers->peers_fe->bind_proc) {
8818 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008819 "running in different processes (%d different ones). "
8820 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008821 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008822 cfgerr++;
8823 }
8824 stop_proxy(curpeers->peers_fe);
8825 curpeers->peers_fe = NULL;
8826 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008827 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008828 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008829 last = &curpeers->next;
8830 continue;
8831 }
8832
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008833 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008834 p = curpeers->remote;
8835 while (p) {
8836 pb = p->next;
8837 free(p->id);
8838 free(p);
8839 p = pb;
8840 }
8841
8842 /* Destroy and unlink this curpeers section.
8843 * Note: curpeers is backed up into *last.
8844 */
8845 free(curpeers->id);
8846 curpeers = curpeers->next;
8847 free(*last);
8848 *last = curpeers;
8849 }
8850 }
8851
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008852 /* initialize stick-tables on backend capable proxies. This must not
8853 * be done earlier because the data size may be discovered while parsing
8854 * other proxies.
8855 */
8856 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8857 if (curproxy->state == PR_STSTOPPED)
8858 continue;
8859
8860 if (!stktable_init(&curproxy->table)) {
8861 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8862 cfgerr++;
8863 }
8864 }
8865
Simon Horman0d16a402015-01-30 11:22:58 +09008866 if (mailers) {
8867 struct mailers *curmailers = mailers, **last;
8868 struct mailer *m, *mb;
8869
8870 /* Remove all mailers sections which don't have a valid listener.
8871 * This can happen when a mailers section is never referenced.
8872 */
8873 last = &mailers;
8874 while (*last) {
8875 curmailers = *last;
8876 if (curmailers->users) {
8877 last = &curmailers->next;
8878 continue;
8879 }
8880
8881 Warning("Removing incomplete section 'mailers %s'.\n",
8882 curmailers->id);
8883
8884 m = curmailers->mailer_list;
8885 while (m) {
8886 mb = m->next;
8887 free(m->id);
8888 free(m);
8889 m = mb;
8890 }
8891
8892 /* Destroy and unlink this curmailers section.
8893 * Note: curmailers is backed up into *last.
8894 */
8895 free(curmailers->id);
8896 curmailers = curmailers->next;
8897 free(*last);
8898 *last = curmailers;
8899 }
8900 }
8901
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008902 /* Update server_state_file_name to backend name if backend is supposed to use
8903 * a server-state file locally defined and none has been provided */
8904 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8905 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
8906 curproxy->server_state_file_name == NULL)
8907 curproxy->server_state_file_name = strdup(curproxy->id);
8908 }
8909
Willy Tarreau34eb6712011-10-24 18:15:04 +02008910 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008911 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008912 MEM_F_SHARED);
8913
Willy Tarreaubb925012009-07-23 13:36:36 +02008914 if (cfgerr > 0)
8915 err_code |= ERR_ALERT | ERR_FATAL;
8916 out:
8917 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008918}
8919
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008920/*
8921 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8922 * parsing sessions.
8923 */
8924void cfg_register_keywords(struct cfg_kw_list *kwl)
8925{
8926 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8927}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008928
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008929/*
8930 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8931 */
8932void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8933{
8934 LIST_DEL(&kwl->list);
8935 LIST_INIT(&kwl->list);
8936}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008937
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008938/* this function register new section in the haproxy configuration file.
8939 * <section_name> is the name of this new section and <section_parser>
8940 * is the called parser. If two section declaration have the same name,
8941 * only the first declared is used.
8942 */
8943int cfg_register_section(char *section_name,
8944 int (*section_parser)(const char *, int, char **, int))
8945{
8946 struct cfg_section *cs;
8947
8948 cs = calloc(1, sizeof(*cs));
8949 if (!cs) {
8950 Alert("register section '%s': out of memory.\n", section_name);
8951 return 0;
8952 }
8953
8954 cs->section_name = section_name;
8955 cs->section_parser = section_parser;
8956
8957 LIST_ADDQ(&sections, &cs->list);
8958
8959 return 1;
8960}
8961
Willy Tarreaubaaee002006-06-26 02:48:02 +02008962/*
David Carlier845efb52015-09-25 11:49:18 +01008963 * free all config section entries
8964 */
8965void cfg_unregister_sections(void)
8966{
8967 struct cfg_section *cs, *ics;
8968
8969 list_for_each_entry_safe(cs, ics, &sections, list) {
8970 LIST_DEL(&cs->list);
8971 free(cs);
8972 }
8973}
8974
8975/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02008976 * Local variables:
8977 * c-indent-level: 8
8978 * c-basic-offset: 8
8979 * End:
8980 */