blob: 92f3611b4e687e753c2e4254e713a981073af7f8 [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 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +01001078 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
1079 Warning("parsing [%s:%d] : uid: string '%s' is not a number.\n | You might want to use the 'user' parameter to use a system user name.\n", file, linenum, args[1]);
1080 err_code |= ERR_WARN;
1081 goto out;
1082 }
1083
Willy Tarreaubaaee002006-06-26 02:48:02 +02001084 }
1085 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001086 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1087 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001088 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001089 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT;
1091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 }
1093 if (*(args[1]) == 0) {
1094 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 }
Baptiste Assmann776e5182016-03-11 17:21:15 +01001098 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
1099 Warning("parsing [%s:%d] : gid: string '%s' is not a number.\n | You might want to use the 'group' parameter to use a system group name.\n", file, linenum, args[1]);
1100 err_code |= ERR_WARN;
1101 goto out;
1102 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001103 }
Simon Horman98637e52014-06-20 12:30:16 +09001104 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001105 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1106 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001107 global.external_check = 1;
1108 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001109 /* user/group name handling */
1110 else if (!strcmp(args[0], "user")) {
1111 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001112 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1113 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001114 if (global.uid != 0) {
1115 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001116 err_code |= ERR_ALERT;
1117 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001118 }
1119 errno = 0;
1120 ha_user = getpwnam(args[1]);
1121 if (ha_user != NULL) {
1122 global.uid = (int)ha_user->pw_uid;
1123 }
1124 else {
1125 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 +02001126 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001127 }
1128 }
1129 else if (!strcmp(args[0], "group")) {
1130 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001131 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1132 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001133 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001134 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001135 err_code |= ERR_ALERT;
1136 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001137 }
1138 errno = 0;
1139 ha_group = getgrnam(args[1]);
1140 if (ha_group != NULL) {
1141 global.gid = (int)ha_group->gr_gid;
1142 }
1143 else {
1144 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 +02001145 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001146 }
1147 }
1148 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001149 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001150 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001152 if (*(args[1]) == 0) {
1153 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001154 err_code |= ERR_ALERT | ERR_FATAL;
1155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 }
1157 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001158 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1159 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1160 file, linenum, args[0], LONGBITS, global.nbproc);
1161 err_code |= ERR_ALERT | ERR_FATAL;
1162 goto out;
1163 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001164 }
1165 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001166 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 if (global.maxconn != 0) {
1169 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001170 err_code |= ERR_ALERT;
1171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001172 }
1173 if (*(args[1]) == 0) {
1174 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001175 err_code |= ERR_ALERT | ERR_FATAL;
1176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001177 }
1178 global.maxconn = atol(args[1]);
1179#ifdef SYSTEM_MAXCONN
1180 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1181 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);
1182 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001183 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001184 }
1185#endif /* SYSTEM_MAXCONN */
1186 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001187 else if (!strcmp(args[0], "maxsslconn")) {
1188#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001189 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1190 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001191 if (*(args[1]) == 0) {
1192 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1193 err_code |= ERR_ALERT | ERR_FATAL;
1194 goto out;
1195 }
1196 global.maxsslconn = atol(args[1]);
1197#else
Emeric Brun0914df82012-10-02 18:45:42 +02001198 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1199 err_code |= ERR_ALERT | ERR_FATAL;
1200 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001201#endif
1202 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001203 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1204#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001205 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1206 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001207 if (*(args[1]) == 0) {
1208 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1209 err_code |= ERR_ALERT | ERR_FATAL;
1210 goto out;
1211 }
1212 free(global.listen_default_ciphers);
1213 global.listen_default_ciphers = strdup(args[1]);
1214#else
1215 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1216 err_code |= ERR_ALERT | ERR_FATAL;
1217 goto out;
1218#endif
1219 }
1220 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1221#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001222 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1223 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001224 if (*(args[1]) == 0) {
1225 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229 free(global.connect_default_ciphers);
1230 global.connect_default_ciphers = strdup(args[1]);
1231#else
1232 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1233 err_code |= ERR_ALERT | ERR_FATAL;
1234 goto out;
1235#endif
1236 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001237#ifdef USE_OPENSSL
1238#ifndef OPENSSL_NO_DH
1239 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1240 if (*(args[1]) == 0) {
1241 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1242 err_code |= ERR_ALERT | ERR_FATAL;
1243 goto out;
1244 }
1245 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1246 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1247 err_code |= ERR_ALERT | ERR_FATAL;
1248 goto out;
1249 }
1250 }
1251#endif
1252#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001253 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001254 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1255 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001256 if (*(args[1]) == 0) {
1257 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1258 err_code |= ERR_ALERT | ERR_FATAL;
1259 goto out;
1260 }
1261 if (strcmp(args[1],"none") == 0)
1262 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1263 else if (strcmp(args[1],"required") == 0)
1264 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1265 else {
1266 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1267 err_code |= ERR_ALERT | ERR_FATAL;
1268 goto out;
1269 }
1270 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001271 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001272 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1273 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001274 if (global.cps_lim != 0) {
1275 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1276 err_code |= ERR_ALERT;
1277 goto out;
1278 }
1279 if (*(args[1]) == 0) {
1280 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1281 err_code |= ERR_ALERT | ERR_FATAL;
1282 goto out;
1283 }
1284 global.cps_lim = atol(args[1]);
1285 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001286 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001287 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1288 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001289 if (global.sps_lim != 0) {
1290 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1291 err_code |= ERR_ALERT;
1292 goto out;
1293 }
1294 if (*(args[1]) == 0) {
1295 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1296 err_code |= ERR_ALERT | ERR_FATAL;
1297 goto out;
1298 }
1299 global.sps_lim = atol(args[1]);
1300 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001301 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001302 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1303 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001304 if (global.ssl_lim != 0) {
1305 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1306 err_code |= ERR_ALERT;
1307 goto out;
1308 }
1309 if (*(args[1]) == 0) {
1310 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1311 err_code |= ERR_ALERT | ERR_FATAL;
1312 goto out;
1313 }
1314 global.ssl_lim = atol(args[1]);
1315 }
William Lallemandd85f9172012-11-09 17:05:39 +01001316 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001317 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1318 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001319 if (*(args[1]) == 0) {
1320 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1321 err_code |= ERR_ALERT | ERR_FATAL;
1322 goto out;
1323 }
1324 global.comp_rate_lim = atoi(args[1]) * 1024;
1325 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001326 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001327 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1328 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001329 if (global.maxpipes != 0) {
1330 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001331 err_code |= ERR_ALERT;
1332 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001333 }
1334 if (*(args[1]) == 0) {
1335 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001336 err_code |= ERR_ALERT | ERR_FATAL;
1337 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001338 }
1339 global.maxpipes = atol(args[1]);
1340 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001341 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001342 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1343 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001344 if (*(args[1]) == 0) {
1345 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1346 err_code |= ERR_ALERT | ERR_FATAL;
1347 goto out;
1348 }
William Lallemande3a7d992012-11-20 11:25:20 +01001349 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001350 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001351 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001352 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1353 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001354 if (*(args[1]) == 0) {
1355 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1356 err_code |= ERR_ALERT | ERR_FATAL;
1357 goto out;
1358 }
1359 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001360 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001361 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1362 err_code |= ERR_ALERT | ERR_FATAL;
1363 goto out;
1364 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001365 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001366
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001368 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001370 if (global.rlimit_nofile != 0) {
1371 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001372 err_code |= ERR_ALERT;
1373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001374 }
1375 if (*(args[1]) == 0) {
1376 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001377 err_code |= ERR_ALERT | ERR_FATAL;
1378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001379 }
1380 global.rlimit_nofile = atol(args[1]);
1381 }
1382 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001383 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 if (global.chroot != NULL) {
1386 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001387 err_code |= ERR_ALERT;
1388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001389 }
1390 if (*(args[1]) == 0) {
1391 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001392 err_code |= ERR_ALERT | ERR_FATAL;
1393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001394 }
1395 global.chroot = strdup(args[1]);
1396 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001397 else if (!strcmp(args[0], "description")) {
1398 int i, len=0;
1399 char *d;
1400
1401 if (!*args[1]) {
1402 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1403 file, linenum, args[0]);
1404 err_code |= ERR_ALERT | ERR_FATAL;
1405 goto out;
1406 }
1407
Willy Tarreau348acfe2014-04-14 15:00:39 +02001408 for (i = 1; *args[i]; i++)
1409 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001410
1411 if (global.desc)
1412 free(global.desc);
1413
1414 global.desc = d = (char *)calloc(1, len);
1415
Willy Tarreau348acfe2014-04-14 15:00:39 +02001416 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1417 for (i = 2; *args[i]; i++)
1418 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001419 }
1420 else if (!strcmp(args[0], "node")) {
1421 int i;
1422 char c;
1423
William Lallemand1a748ae2015-05-19 16:37:23 +02001424 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1425 goto out;
1426
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001427 for (i=0; args[1][i]; i++) {
1428 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001429 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1430 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001431 break;
1432 }
1433
1434 if (!i || args[1][i]) {
1435 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1436 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1437 file, linenum, args[0]);
1438 err_code |= ERR_ALERT | ERR_FATAL;
1439 goto out;
1440 }
1441
1442 if (global.node)
1443 free(global.node);
1444
1445 global.node = strdup(args[1]);
1446 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001447 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001448 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450 if (global.pidfile != NULL) {
1451 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001452 err_code |= ERR_ALERT;
1453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454 }
1455 if (*(args[1]) == 0) {
1456 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001457 err_code |= ERR_ALERT | ERR_FATAL;
1458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459 }
1460 global.pidfile = strdup(args[1]);
1461 }
Emeric Bruned760922010-10-22 17:59:25 +02001462 else if (!strcmp(args[0], "unix-bind")) {
1463 int cur_arg = 1;
1464 while (*(args[cur_arg])) {
1465 if (!strcmp(args[cur_arg], "prefix")) {
1466 if (global.unix_bind.prefix != NULL) {
1467 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1468 err_code |= ERR_ALERT;
1469 cur_arg += 2;
1470 continue;
1471 }
1472
1473 if (*(args[cur_arg+1]) == 0) {
1474 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1475 err_code |= ERR_ALERT | ERR_FATAL;
1476 goto out;
1477 }
1478 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1479 cur_arg += 2;
1480 continue;
1481 }
1482
1483 if (!strcmp(args[cur_arg], "mode")) {
1484
1485 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1486 cur_arg += 2;
1487 continue;
1488 }
1489
1490 if (!strcmp(args[cur_arg], "uid")) {
1491
1492 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1493 cur_arg += 2;
1494 continue;
1495 }
1496
1497 if (!strcmp(args[cur_arg], "gid")) {
1498
1499 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1500 cur_arg += 2;
1501 continue;
1502 }
1503
1504 if (!strcmp(args[cur_arg], "user")) {
1505 struct passwd *user;
1506
1507 user = getpwnam(args[cur_arg + 1]);
1508 if (!user) {
1509 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1510 file, linenum, args[0], args[cur_arg + 1 ]);
1511 err_code |= ERR_ALERT | ERR_FATAL;
1512 goto out;
1513 }
1514
1515 global.unix_bind.ux.uid = user->pw_uid;
1516 cur_arg += 2;
1517 continue;
1518 }
1519
1520 if (!strcmp(args[cur_arg], "group")) {
1521 struct group *group;
1522
1523 group = getgrnam(args[cur_arg + 1]);
1524 if (!group) {
1525 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1526 file, linenum, args[0], args[cur_arg + 1 ]);
1527 err_code |= ERR_ALERT | ERR_FATAL;
1528 goto out;
1529 }
1530
1531 global.unix_bind.ux.gid = group->gr_gid;
1532 cur_arg += 2;
1533 continue;
1534 }
1535
Willy Tarreaub48f9582011-09-05 01:17:06 +02001536 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001537 file, linenum, args[0]);
1538 err_code |= ERR_ALERT | ERR_FATAL;
1539 goto out;
1540 }
1541 }
William Lallemand0f99e342011-10-12 17:50:54 +02001542 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1543 /* delete previous herited or defined syslog servers */
1544 struct logsrv *back;
1545 struct logsrv *tmp;
1546
1547 if (*(args[1]) != 0) {
1548 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1549 err_code |= ERR_ALERT | ERR_FATAL;
1550 goto out;
1551 }
1552
1553 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1554 LIST_DEL(&tmp->list);
1555 free(tmp);
1556 }
1557 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001559 struct sockaddr_storage *sk;
1560 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001561 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001562 int arg = 0;
1563 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001564
William Lallemand1a748ae2015-05-19 16:37:23 +02001565 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1566 goto out;
1567
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568 if (*(args[1]) == 0 || *(args[2]) == 0) {
1569 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001570 err_code |= ERR_ALERT | ERR_FATAL;
1571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001572 }
William Lallemand0f99e342011-10-12 17:50:54 +02001573
1574 logsrv = calloc(1, sizeof(struct logsrv));
1575
Willy Tarreau18324f52014-06-27 18:10:07 +02001576 /* just after the address, a length may be specified */
1577 if (strcmp(args[arg+2], "len") == 0) {
1578 len = atoi(args[arg+3]);
1579 if (len < 80 || len > 65535) {
1580 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1581 file, linenum, args[arg+3]);
1582 err_code |= ERR_ALERT | ERR_FATAL;
1583 goto out;
1584 }
1585 logsrv->maxlen = len;
1586
1587 /* skip these two args */
1588 arg += 2;
1589 }
1590 else
1591 logsrv->maxlen = MAX_SYSLOG_LEN;
1592
1593 if (logsrv->maxlen > global.max_syslog_len) {
1594 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02001595 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02001596 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001597 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02001598 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001599 }
1600
Dragan Dosen1322d092015-09-22 16:05:32 +02001601 /* after the length, a format may be specified */
1602 if (strcmp(args[arg+2], "format") == 0) {
1603 logsrv->format = get_log_format(args[arg+3]);
1604 if (logsrv->format < 0) {
1605 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1606 err_code |= ERR_ALERT | ERR_FATAL;
1607 goto out;
1608 }
1609
1610 /* skip these two args */
1611 arg += 2;
1612 }
1613
William Lallemand1a748ae2015-05-19 16:37:23 +02001614 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1615 goto out;
1616
Willy Tarreau18324f52014-06-27 18:10:07 +02001617 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001618 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001619 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001620 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001621 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622 }
1623
William Lallemand0f99e342011-10-12 17:50:54 +02001624 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001625 if (*(args[arg+3])) {
1626 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001627 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001628 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001629 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001630 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 }
1632 }
1633
William Lallemand0f99e342011-10-12 17:50:54 +02001634 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001635 if (*(args[arg+4])) {
1636 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001637 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001638 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001639 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001640 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001641 }
1642 }
1643
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001644 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001645 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001646 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001647 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001648 free(logsrv);
1649 goto out;
1650 }
1651 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001652
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001653 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001654 if (port1 != port2) {
1655 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1656 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001657 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001658 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001659 goto out;
1660 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001661
William Lallemand0f99e342011-10-12 17:50:54 +02001662 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001663 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001664 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001665 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001666
William Lallemand0f99e342011-10-12 17:50:54 +02001667 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001668 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001669 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1670 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001671
1672 if (global.log_send_hostname != NULL) {
1673 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1674 err_code |= ERR_ALERT;
1675 goto out;
1676 }
1677
1678 if (*(args[1]))
1679 name = args[1];
1680 else
1681 name = hostname;
1682
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001683 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001684 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001685 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001686 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1687 if (global.server_state_base != NULL) {
1688 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1689 err_code |= ERR_ALERT;
1690 goto out;
1691 }
1692
1693 if (!*(args[1])) {
1694 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1695 err_code |= ERR_FATAL;
1696 goto out;
1697 }
1698
1699 global.server_state_base = strdup(args[1]);
1700 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001701 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1702 if (global.server_state_file != NULL) {
1703 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1704 err_code |= ERR_ALERT;
1705 goto out;
1706 }
1707
1708 if (!*(args[1])) {
1709 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1710 err_code |= ERR_FATAL;
1711 goto out;
1712 }
1713
1714 global.server_state_file = strdup(args[1]);
1715 }
Kevinm48936af2010-12-22 16:08:21 +00001716 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001717 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1718 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001719 if (*(args[1]) == 0) {
1720 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1721 err_code |= ERR_ALERT | ERR_FATAL;
1722 goto out;
1723 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001724 chunk_destroy(&global.log_tag);
1725 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001726 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001727 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001728 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1729 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001730 if (global.spread_checks != 0) {
1731 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001732 err_code |= ERR_ALERT;
1733 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001734 }
1735 if (*(args[1]) == 0) {
1736 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001737 err_code |= ERR_ALERT | ERR_FATAL;
1738 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001739 }
1740 global.spread_checks = atol(args[1]);
1741 if (global.spread_checks < 0 || global.spread_checks > 50) {
1742 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001743 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001744 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001745 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001746 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1747 const char *err;
1748 unsigned int val;
1749
William Lallemand1a748ae2015-05-19 16:37:23 +02001750 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1751 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001752 if (*(args[1]) == 0) {
1753 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1754 err_code |= ERR_ALERT | ERR_FATAL;
1755 goto out;
1756 }
1757
1758 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1759 if (err) {
1760 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1761 err_code |= ERR_ALERT | ERR_FATAL;
1762 }
1763 global.max_spread_checks = val;
1764 if (global.max_spread_checks < 0) {
1765 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1766 err_code |= ERR_ALERT | ERR_FATAL;
1767 }
1768 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001769 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1770#ifdef USE_CPU_AFFINITY
1771 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001772 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001773 unsigned long cpus = 0;
1774
1775 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001776 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001777 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001778 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001779 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001780 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001781 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001782 proc = atol(args[1]);
1783 if (proc >= 1 && proc <= LONGBITS)
1784 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001785 }
1786
1787 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001788 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",
1789 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001790 err_code |= ERR_ALERT | ERR_FATAL;
1791 goto out;
1792 }
1793
1794 cur_arg = 2;
1795 while (*args[cur_arg]) {
1796 unsigned int low, high;
1797
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001798 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001799 char *dash = strchr(args[cur_arg], '-');
1800
1801 low = high = str2uic(args[cur_arg]);
1802 if (dash)
1803 high = str2uic(dash + 1);
1804
1805 if (high < low) {
1806 unsigned int swap = low;
1807 low = high;
1808 high = swap;
1809 }
1810
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001811 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001812 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001813 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001814 err_code |= ERR_ALERT | ERR_FATAL;
1815 goto out;
1816 }
1817
1818 while (low <= high)
1819 cpus |= 1UL << low++;
1820 }
1821 else {
1822 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1823 file, linenum, args[0], args[cur_arg]);
1824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
1826 }
1827 cur_arg++;
1828 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001829 for (i = 0; i < LONGBITS; i++)
1830 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001831 global.cpu_map[i] = cpus;
1832#else
1833 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1834 err_code |= ERR_ALERT | ERR_FATAL;
1835 goto out;
1836#endif
1837 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001838 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1839 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1840 goto out;
1841
1842 if (*(args[2]) == 0) {
1843 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1844 err_code |= ERR_ALERT | ERR_FATAL;
1845 goto out;
1846 }
1847
1848 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1849 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1850 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1851 err_code |= ERR_ALERT | ERR_FATAL;
1852 goto out;
1853 }
1854 }
1855 else if (!strcmp(args[0], "unsetenv")) {
1856 int arg;
1857
1858 if (*(args[1]) == 0) {
1859 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1860 err_code |= ERR_ALERT | ERR_FATAL;
1861 goto out;
1862 }
1863
1864 for (arg = 1; *args[arg]; arg++) {
1865 if (unsetenv(args[arg]) != 0) {
1866 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1867 err_code |= ERR_ALERT | ERR_FATAL;
1868 goto out;
1869 }
1870 }
1871 }
1872 else if (!strcmp(args[0], "resetenv")) {
1873 extern char **environ;
1874 char **env = environ;
1875
1876 /* args contain variable names to keep, one per argument */
1877 while (*env) {
1878 int arg;
1879
1880 /* look for current variable in among all those we want to keep */
1881 for (arg = 1; *args[arg]; arg++) {
1882 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1883 (*env)[strlen(args[arg])] == '=')
1884 break;
1885 }
1886
1887 /* delete this variable */
1888 if (!*args[arg]) {
1889 char *delim = strchr(*env, '=');
1890
1891 if (!delim || delim - *env >= trash.size) {
1892 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1893 err_code |= ERR_ALERT | ERR_FATAL;
1894 goto out;
1895 }
1896
1897 memcpy(trash.str, *env, delim - *env);
1898 trash.str[delim - *env] = 0;
1899
1900 if (unsetenv(trash.str) != 0) {
1901 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1902 err_code |= ERR_ALERT | ERR_FATAL;
1903 goto out;
1904 }
1905 }
1906 else
1907 env++;
1908 }
1909 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001910 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001911 struct cfg_kw_list *kwl;
1912 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001913 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001914
1915 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1916 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1917 if (kwl->kw[index].section != CFG_GLOBAL)
1918 continue;
1919 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001920 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001921 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001922 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001923 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001924 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001925 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001926 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001927 err_code |= ERR_WARN;
1928 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001929 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001930 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001931 }
1932 }
1933 }
1934
Willy Tarreaubaaee002006-06-26 02:48:02 +02001935 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001936 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001938
Willy Tarreau058e9072009-07-20 09:30:05 +02001939 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001940 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001941 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001942}
1943
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001944void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001946 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001947 defproxy.mode = PR_MODE_TCP;
1948 defproxy.state = PR_STNEW;
1949 defproxy.maxconn = cfg_maxpconn;
1950 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001951 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001952
Simon Horman66183002013-02-23 10:16:43 +09001953 defproxy.defsrv.check.inter = DEF_CHKINTR;
1954 defproxy.defsrv.check.fastinter = 0;
1955 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001956 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1957 defproxy.defsrv.agent.fastinter = 0;
1958 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001959 defproxy.defsrv.check.rise = DEF_RISETIME;
1960 defproxy.defsrv.check.fall = DEF_FALLTIME;
1961 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1962 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001963 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001964 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001965 defproxy.defsrv.maxqueue = 0;
1966 defproxy.defsrv.minconn = 0;
1967 defproxy.defsrv.maxconn = 0;
1968 defproxy.defsrv.slowstart = 0;
1969 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1970 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1971 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001972
1973 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001974 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001975}
1976
Willy Tarreauade5ec42010-01-28 19:33:49 +01001977
Willy Tarreau63af98d2014-05-18 08:11:41 +02001978/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1979 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1980 * ERR_FATAL in case of error.
1981 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001982static int create_cond_regex_rule(const char *file, int line,
1983 struct proxy *px, int dir, int action, int flags,
1984 const char *cmd, const char *reg, const char *repl,
1985 const char **cond_start)
1986{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001987 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001988 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001989 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001990 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001991 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001992 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001993 int cs;
1994 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001995
1996 if (px == &defproxy) {
1997 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001998 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001999 goto err;
2000 }
2001
2002 if (*reg == 0) {
2003 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002004 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002005 goto err;
2006 }
2007
2008 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002009 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002010
Willy Tarreau5321c422010-01-28 20:35:13 +01002011 if (cond_start &&
2012 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002013 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
2014 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
2015 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002016 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002017 goto err;
2018 }
2019 }
2020 else if (cond_start && **cond_start) {
2021 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
2022 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002023 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002024 goto err;
2025 }
2026
Willy Tarreau63af98d2014-05-18 08:11:41 +02002027 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002028 (dir == SMP_OPT_DIR_REQ) ?
2029 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
2030 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
2031 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01002032
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002033 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01002034 if (!preg) {
2035 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002036 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002037 goto err;
2038 }
2039
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002040 cs = !(flags & REG_ICASE);
2041 cap = !(flags & REG_NOSUB);
2042 error = NULL;
2043 if (!regex_comp(reg, preg, cs, cap, &error)) {
2044 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
2045 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002046 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002047 goto err;
2048 }
2049
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002050 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01002051 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002052 if (repl && err) {
2053 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
2054 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002055 ret_code |= ERR_ALERT | ERR_FATAL;
2056 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002057 }
2058
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002059 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002060 ret_code |= ERR_WARN;
2061
2062 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002063
Willy Tarreau63af98d2014-05-18 08:11:41 +02002064 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002065 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002066 err:
2067 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002068 free(errmsg);
2069 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002070}
2071
Willy Tarreaubaaee002006-06-26 02:48:02 +02002072/*
William Lallemand51097192015-04-14 16:35:22 +02002073 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02002074 * Returns the error code, 0 if OK, or any combination of :
2075 * - ERR_ABORT: must abort ASAP
2076 * - ERR_FATAL: we can continue parsing but not start the service
2077 * - ERR_WARN: a warning has been emitted
2078 * - ERR_ALERT: an alert has been emitted
2079 * Only the two first ones can stop processing, the two others are just
2080 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002081 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002082int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2083{
2084 static struct peers *curpeers = NULL;
2085 struct peer *newpeer = NULL;
2086 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002087 struct bind_conf *bind_conf;
2088 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002089 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002090 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002091
2092 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002093 if (!*args[1]) {
2094 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002095 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002096 goto out;
2097 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002098
William Lallemand6e62fb62015-04-28 16:55:23 +02002099 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2100 goto out;
2101
Emeric Brun32da3c42010-09-23 18:39:19 +02002102 err = invalid_char(args[1]);
2103 if (err) {
2104 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2105 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002106 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002107 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002108 }
2109
2110 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2111 /*
2112 * If there are two proxies with the same name only following
2113 * combinations are allowed:
2114 */
2115 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002116 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 +02002117 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002118 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002119 }
2120 }
2121
2122 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
2123 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2124 err_code |= ERR_ALERT | ERR_ABORT;
2125 goto out;
2126 }
2127
2128 curpeers->next = peers;
2129 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002130 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002131 curpeers->conf.line = linenum;
2132 curpeers->last_change = now.tv_sec;
2133 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002134 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002135 }
2136 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002137 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002138 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002139 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002140
2141 if (!*args[2]) {
2142 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2143 file, linenum, args[0]);
2144 err_code |= ERR_ALERT | ERR_FATAL;
2145 goto out;
2146 }
2147
2148 err = invalid_char(args[1]);
2149 if (err) {
2150 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2151 file, linenum, *err, args[1]);
2152 err_code |= ERR_ALERT | ERR_FATAL;
2153 goto out;
2154 }
2155
2156 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2157 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2158 err_code |= ERR_ALERT | ERR_ABORT;
2159 goto out;
2160 }
2161
2162 /* the peers are linked backwards first */
2163 curpeers->count++;
2164 newpeer->next = curpeers->remote;
2165 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002166 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002167 newpeer->conf.line = linenum;
2168
2169 newpeer->last_change = now.tv_sec;
2170 newpeer->id = strdup(args[1]);
2171
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002172 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002173 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002174 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002175 err_code |= ERR_ALERT | ERR_FATAL;
2176 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002177 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002178
2179 proto = protocol_by_family(sk->ss_family);
2180 if (!proto || !proto->connect) {
2181 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2182 file, linenum, args[0], args[1]);
2183 err_code |= ERR_ALERT | ERR_FATAL;
2184 goto out;
2185 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002186
2187 if (port1 != port2) {
2188 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2189 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002190 err_code |= ERR_ALERT | ERR_FATAL;
2191 goto out;
2192 }
2193
Willy Tarreau2aa38802013-02-20 19:20:59 +01002194 if (!port1) {
2195 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2196 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
2199 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002200
Emeric Brun32da3c42010-09-23 18:39:19 +02002201 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002202 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002203 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002204 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002205
Emeric Brun32da3c42010-09-23 18:39:19 +02002206 if (strcmp(newpeer->id, localpeer) == 0) {
2207 /* Current is local peer, it define a frontend */
2208 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002209 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002210
2211 if (!curpeers->peers_fe) {
2212 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2213 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2214 err_code |= ERR_ALERT | ERR_ABORT;
2215 goto out;
2216 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002217
Willy Tarreau237250c2011-07-29 01:49:03 +02002218 init_new_proxy(curpeers->peers_fe);
2219 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002220 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002221 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2222 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002223 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002224
2225 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2226
Willy Tarreau902636f2013-03-10 19:44:48 +01002227 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2228 if (errmsg && *errmsg) {
2229 indent_msg(&errmsg, 2);
2230 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002231 }
2232 else
2233 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2234 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002235 err_code |= ERR_FATAL;
2236 goto out;
2237 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002238
2239 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002240 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002241 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2242 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002243 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002244 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002245 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002246 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002247 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2248 global.maxsock += l->maxconn;
2249 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002250 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002251 else {
2252 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2253 file, linenum, args[0], args[1],
2254 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2255 err_code |= ERR_FATAL;
2256 goto out;
2257 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002258 }
2259 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002260 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2261 curpeers->state = PR_STSTOPPED;
2262 }
2263 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2264 curpeers->state = PR_STNEW;
2265 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002266 else if (*args[0] != 0) {
2267 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2268 err_code |= ERR_ALERT | ERR_FATAL;
2269 goto out;
2270 }
2271
2272out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002273 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002274 return err_code;
2275}
2276
Baptiste Assmann325137d2015-04-13 23:40:55 +02002277/*
2278 * Parse a <resolvers> section.
2279 * Returns the error code, 0 if OK, or any combination of :
2280 * - ERR_ABORT: must abort ASAP
2281 * - ERR_FATAL: we can continue parsing but not start the service
2282 * - ERR_WARN: a warning has been emitted
2283 * - ERR_ALERT: an alert has been emitted
2284 * Only the two first ones can stop processing, the two others are just
2285 * indicators.
2286 */
2287int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2288{
2289 static struct dns_resolvers *curr_resolvers = NULL;
2290 struct dns_nameserver *newnameserver = NULL;
2291 const char *err;
2292 int err_code = 0;
2293 char *errmsg = NULL;
2294
2295 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2296 if (!*args[1]) {
2297 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2298 err_code |= ERR_ALERT | ERR_ABORT;
2299 goto out;
2300 }
2301
2302 err = invalid_char(args[1]);
2303 if (err) {
2304 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2305 file, linenum, *err, args[0], args[1]);
2306 err_code |= ERR_ALERT | ERR_ABORT;
2307 goto out;
2308 }
2309
2310 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2311 /* Error if two resolvers owns the same name */
2312 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2313 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2314 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2315 err_code |= ERR_ALERT | ERR_ABORT;
2316 }
2317 }
2318
2319 if ((curr_resolvers = (struct dns_resolvers *)calloc(1, sizeof(struct dns_resolvers))) == NULL) {
2320 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2321 err_code |= ERR_ALERT | ERR_ABORT;
2322 goto out;
2323 }
2324
2325 /* default values */
2326 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2327 curr_resolvers->conf.file = strdup(file);
2328 curr_resolvers->conf.line = linenum;
2329 curr_resolvers->id = strdup(args[1]);
2330 curr_resolvers->query_ids = EB_ROOT;
2331 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002332 curr_resolvers->hold.valid = 10000;
2333 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002334 curr_resolvers->resolve_retries = 3;
2335 LIST_INIT(&curr_resolvers->nameserver_list);
2336 LIST_INIT(&curr_resolvers->curr_resolution);
2337 }
2338 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2339 struct sockaddr_storage *sk;
2340 int port1, port2;
2341 struct protocol *proto;
2342
2343 if (!*args[2]) {
2344 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2345 file, linenum, args[0]);
2346 err_code |= ERR_ALERT | ERR_FATAL;
2347 goto out;
2348 }
2349
2350 err = invalid_char(args[1]);
2351 if (err) {
2352 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2353 file, linenum, *err, args[1]);
2354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
2356 }
2357
Baptiste Assmanna315c552015-11-02 22:55:49 +01002358 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2359 /* Error if two resolvers owns the same name */
2360 if (strcmp(newnameserver->id, args[1]) == 0) {
2361 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2362 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2363 err_code |= ERR_ALERT | ERR_FATAL;
2364 }
2365 }
2366
Baptiste Assmann325137d2015-04-13 23:40:55 +02002367 if ((newnameserver = (struct dns_nameserver *)calloc(1, sizeof(struct dns_nameserver))) == NULL) {
2368 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2369 err_code |= ERR_ALERT | ERR_ABORT;
2370 goto out;
2371 }
2372
2373 /* the nameservers are linked backward first */
2374 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2375 curr_resolvers->count_nameservers++;
2376 newnameserver->resolvers = curr_resolvers;
2377 newnameserver->conf.file = strdup(file);
2378 newnameserver->conf.line = linenum;
2379 newnameserver->id = strdup(args[1]);
2380
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002381 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002382 if (!sk) {
2383 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2384 err_code |= ERR_ALERT | ERR_FATAL;
2385 goto out;
2386 }
2387
2388 proto = protocol_by_family(sk->ss_family);
2389 if (!proto || !proto->connect) {
2390 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2391 file, linenum, args[0], args[1]);
2392 err_code |= ERR_ALERT | ERR_FATAL;
2393 goto out;
2394 }
2395
2396 if (port1 != port2) {
2397 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2398 file, linenum, args[0], args[1], args[2]);
2399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
2401 }
2402
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002403 if (!port1 && !port2) {
2404 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2405 file, linenum, args[0], args[1]);
2406 err_code |= ERR_ALERT | ERR_FATAL;
2407 goto out;
2408 }
2409
Baptiste Assmann325137d2015-04-13 23:40:55 +02002410 newnameserver->addr = *sk;
2411 }
2412 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2413 const char *res;
2414 unsigned int time;
2415
2416 if (!*args[2]) {
2417 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2418 file, linenum, args[0]);
2419 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
2422 }
2423 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2424 if (res) {
2425 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2426 file, linenum, *res, args[0]);
2427 err_code |= ERR_ALERT | ERR_FATAL;
2428 goto out;
2429 }
2430 if (strcmp(args[1], "valid") == 0)
2431 curr_resolvers->hold.valid = time;
2432 else {
2433 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2434 file, linenum, args[0], args[1]);
2435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
2437 }
2438
2439 }
2440 else if (strcmp(args[0], "resolve_retries") == 0) {
2441 if (!*args[1]) {
2442 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2443 file, linenum, args[0]);
2444 err_code |= ERR_ALERT | ERR_FATAL;
2445 goto out;
2446 }
2447 curr_resolvers->resolve_retries = atoi(args[1]);
2448 }
2449 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002450 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002451 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2452 file, linenum, args[0]);
2453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
2455 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002456 else if (strcmp(args[1], "retry") == 0) {
2457 const char *res;
2458 unsigned int timeout_retry;
2459
2460 if (!*args[2]) {
2461 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2462 file, linenum, args[0], args[1]);
2463 err_code |= ERR_ALERT | ERR_FATAL;
2464 goto out;
2465 }
2466 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2467 if (res) {
2468 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2469 file, linenum, *res, args[0], args[1]);
2470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
2472 }
2473 curr_resolvers->timeout.retry = timeout_retry;
2474 }
2475 else {
2476 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2477 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002478 err_code |= ERR_ALERT | ERR_FATAL;
2479 goto out;
2480 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002481 } /* neither "nameserver" nor "resolvers" */
2482 else if (*args[0] != 0) {
2483 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2484 err_code |= ERR_ALERT | ERR_FATAL;
2485 goto out;
2486 }
2487
2488 out:
2489 free(errmsg);
2490 return err_code;
2491}
Simon Horman0d16a402015-01-30 11:22:58 +09002492
2493/*
William Lallemand51097192015-04-14 16:35:22 +02002494 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002495 * Returns the error code, 0 if OK, or any combination of :
2496 * - ERR_ABORT: must abort ASAP
2497 * - ERR_FATAL: we can continue parsing but not start the service
2498 * - ERR_WARN: a warning has been emitted
2499 * - ERR_ALERT: an alert has been emitted
2500 * Only the two first ones can stop processing, the two others are just
2501 * indicators.
2502 */
2503int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2504{
2505 static struct mailers *curmailers = NULL;
2506 struct mailer *newmailer = NULL;
2507 const char *err;
2508 int err_code = 0;
2509 char *errmsg = NULL;
2510
2511 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2512 if (!*args[1]) {
2513 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2514 err_code |= ERR_ALERT | ERR_ABORT;
2515 goto out;
2516 }
2517
2518 err = invalid_char(args[1]);
2519 if (err) {
2520 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2521 file, linenum, *err, args[0], args[1]);
2522 err_code |= ERR_ALERT | ERR_ABORT;
2523 goto out;
2524 }
2525
2526 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2527 /*
2528 * If there are two proxies with the same name only following
2529 * combinations are allowed:
2530 */
2531 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002532 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 +09002533 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002534 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002535 }
2536 }
2537
2538 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2539 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2540 err_code |= ERR_ALERT | ERR_ABORT;
2541 goto out;
2542 }
2543
2544 curmailers->next = mailers;
2545 mailers = curmailers;
2546 curmailers->conf.file = strdup(file);
2547 curmailers->conf.line = linenum;
2548 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002549 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2550 * But need enough time so that timeouts don't occur
2551 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002552 }
2553 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2554 struct sockaddr_storage *sk;
2555 int port1, port2;
2556 struct protocol *proto;
2557
2558 if (!*args[2]) {
2559 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2560 file, linenum, args[0]);
2561 err_code |= ERR_ALERT | ERR_FATAL;
2562 goto out;
2563 }
2564
2565 err = invalid_char(args[1]);
2566 if (err) {
2567 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2568 file, linenum, *err, args[1]);
2569 err_code |= ERR_ALERT | ERR_FATAL;
2570 goto out;
2571 }
2572
2573 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2574 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2575 err_code |= ERR_ALERT | ERR_ABORT;
2576 goto out;
2577 }
2578
2579 /* the mailers are linked backwards first */
2580 curmailers->count++;
2581 newmailer->next = curmailers->mailer_list;
2582 curmailers->mailer_list = newmailer;
2583 newmailer->mailers = curmailers;
2584 newmailer->conf.file = strdup(file);
2585 newmailer->conf.line = linenum;
2586
2587 newmailer->id = strdup(args[1]);
2588
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002589 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002590 if (!sk) {
2591 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2592 err_code |= ERR_ALERT | ERR_FATAL;
2593 goto out;
2594 }
2595
2596 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002597 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2598 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002599 file, linenum, args[0], args[1]);
2600 err_code |= ERR_ALERT | ERR_FATAL;
2601 goto out;
2602 }
2603
2604 if (port1 != port2) {
2605 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2606 file, linenum, args[0], args[1], args[2]);
2607 err_code |= ERR_ALERT | ERR_FATAL;
2608 goto out;
2609 }
2610
2611 if (!port1) {
2612 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2613 file, linenum, args[0], args[1], args[2]);
2614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
2616 }
2617
2618 newmailer->addr = *sk;
2619 newmailer->proto = proto;
2620 newmailer->xprt = &raw_sock;
2621 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002622 }
2623 else if (strcmp(args[0], "timeout") == 0) {
2624 if (!*args[1]) {
2625 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2626 file, linenum, args[0]);
2627 err_code |= ERR_ALERT | ERR_FATAL;
2628 goto out;
2629 }
2630 else if (strcmp(args[1], "mail") == 0) {
2631 const char *res;
2632 unsigned int timeout_mail;
2633 if (!*args[2]) {
2634 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2635 file, linenum, args[0], args[1]);
2636 err_code |= ERR_ALERT | ERR_FATAL;
2637 goto out;
2638 }
2639 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2640 if (res) {
2641 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2642 file, linenum, *res, args[0]);
2643 err_code |= ERR_ALERT | ERR_FATAL;
2644 goto out;
2645 }
2646 if (timeout_mail <= 0) {
2647 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
2650 }
2651 curmailers->timeout.mail = timeout_mail;
2652 } else {
2653 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2654 file, linenum, args[0], args[1]);
2655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
2657 }
2658 }
Simon Horman0d16a402015-01-30 11:22:58 +09002659 else if (*args[0] != 0) {
2660 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2661 err_code |= ERR_ALERT | ERR_FATAL;
2662 goto out;
2663 }
2664
2665out:
2666 free(errmsg);
2667 return err_code;
2668}
2669
Simon Horman9dc49962015-01-30 11:22:59 +09002670static void free_email_alert(struct proxy *p)
2671{
2672 free(p->email_alert.mailers.name);
2673 p->email_alert.mailers.name = NULL;
2674 free(p->email_alert.from);
2675 p->email_alert.from = NULL;
2676 free(p->email_alert.to);
2677 p->email_alert.to = NULL;
2678 free(p->email_alert.myhostname);
2679 p->email_alert.myhostname = NULL;
2680}
2681
Willy Tarreau3842f002009-06-14 11:39:52 +02002682int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002683{
2684 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002685 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002686 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002687 int rc;
2688 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002689 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002690 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002691 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002692 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002693 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002694
Willy Tarreau977b8e42006-12-29 14:19:17 +01002695 if (!strcmp(args[0], "listen"))
2696 rc = PR_CAP_LISTEN;
2697 else if (!strcmp(args[0], "frontend"))
2698 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002699 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002700 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002701 else
2702 rc = PR_CAP_NONE;
2703
2704 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 if (!*args[1]) {
2706 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2707 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2708 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002709 err_code |= ERR_ALERT | ERR_ABORT;
2710 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002711 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002712
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002713 err = invalid_char(args[1]);
2714 if (err) {
2715 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2716 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002717 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002718 }
2719
Willy Tarreau8f50b682015-05-26 11:45:02 +02002720 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2721 if (curproxy) {
2722 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2723 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2724 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002725 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002726 }
2727
Willy Tarreaubaaee002006-06-26 02:48:02 +02002728 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2729 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002730 err_code |= ERR_ALERT | ERR_ABORT;
2731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002732 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002733
Willy Tarreau97cb7802010-01-03 20:23:58 +01002734 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002735 curproxy->next = proxy;
2736 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002737 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2738 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002739 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002740 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002741 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002742 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002743
William Lallemand6e62fb62015-04-28 16:55:23 +02002744 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2745 if (curproxy->cap & PR_CAP_FE)
2746 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2747 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002748 }
2749
2750 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002751 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002752 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002753
Willy Tarreaubaaee002006-06-26 02:48:02 +02002754 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002755 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002756 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002757 curproxy->no_options = defproxy.no_options;
2758 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002759 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002760 curproxy->except_net = defproxy.except_net;
2761 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002762 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002763 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002764
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002765 if (defproxy.fwdfor_hdr_len) {
2766 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2767 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2768 }
2769
Willy Tarreaub86db342009-11-30 11:50:16 +01002770 if (defproxy.orgto_hdr_len) {
2771 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2772 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2773 }
2774
Mark Lamourinec2247f02012-01-04 13:02:01 -05002775 if (defproxy.server_id_hdr_len) {
2776 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2777 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2778 }
2779
Willy Tarreau977b8e42006-12-29 14:19:17 +01002780 if (curproxy->cap & PR_CAP_FE) {
2781 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002782 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002783 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002784
2785 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002786 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2787 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002788
2789 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2790 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002791
Willy Tarreau977b8e42006-12-29 14:19:17 +01002792 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002793 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002794 curproxy->fullconn = defproxy.fullconn;
2795 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002796 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002797 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002798
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002799 if (defproxy.check_req) {
2800 curproxy->check_req = calloc(1, defproxy.check_len);
2801 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2802 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002803 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002804
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002805 if (defproxy.expect_str) {
2806 curproxy->expect_str = strdup(defproxy.expect_str);
2807 if (defproxy.expect_regex) {
2808 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002809 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2810 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002811 }
2812 }
2813
Willy Tarreau67402132012-05-31 20:40:20 +02002814 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002815 if (defproxy.cookie_name)
2816 curproxy->cookie_name = strdup(defproxy.cookie_name);
2817 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002818 if (defproxy.cookie_domain)
2819 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002820
Willy Tarreau31936852010-10-06 16:59:56 +02002821 if (defproxy.cookie_maxidle)
2822 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2823
2824 if (defproxy.cookie_maxlife)
2825 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2826
Emeric Brun647caf12009-06-30 17:57:00 +02002827 if (defproxy.rdp_cookie_name)
2828 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2829 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2830
Willy Tarreau01732802007-11-01 22:48:15 +01002831 if (defproxy.url_param_name)
2832 curproxy->url_param_name = strdup(defproxy.url_param_name);
2833 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002834
Benoitaffb4812009-03-25 13:02:10 +01002835 if (defproxy.hh_name)
2836 curproxy->hh_name = strdup(defproxy.hh_name);
2837 curproxy->hh_len = defproxy.hh_len;
2838 curproxy->hh_match_domain = defproxy.hh_match_domain;
2839
Willy Tarreauef9a3602012-12-08 22:29:20 +01002840 if (defproxy.conn_src.iface_name)
2841 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2842 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002843 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002844#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002845 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002846#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002847 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002848 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002849
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002850 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002851 if (defproxy.capture_name)
2852 curproxy->capture_name = strdup(defproxy.capture_name);
2853 curproxy->capture_namelen = defproxy.capture_namelen;
2854 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002855 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002856
Willy Tarreau977b8e42006-12-29 14:19:17 +01002857 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002858 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002859 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002860 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002861 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002862 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002863 curproxy->mon_net = defproxy.mon_net;
2864 curproxy->mon_mask = defproxy.mon_mask;
2865 if (defproxy.monitor_uri)
2866 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2867 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002868 if (defproxy.defbe.name)
2869 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002870
2871 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002872 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2873 if (curproxy->conf.logformat_string &&
2874 curproxy->conf.logformat_string != default_http_log_format &&
2875 curproxy->conf.logformat_string != default_tcp_log_format &&
2876 curproxy->conf.logformat_string != clf_http_log_format)
2877 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2878
2879 if (defproxy.conf.lfs_file) {
2880 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2881 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2882 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002883
2884 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2885 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2886 if (curproxy->conf.logformat_sd_string &&
2887 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2888 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2889
2890 if (defproxy.conf.lfsd_file) {
2891 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2892 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2893 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002894 }
2895
2896 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002897 curproxy->timeout.connect = defproxy.timeout.connect;
2898 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002899 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002900 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002901 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002902 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002903 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002904 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002905 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002906 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002907 }
2908
Willy Tarreaubaaee002006-06-26 02:48:02 +02002909 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002910 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002911
2912 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002913 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002914 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002915 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002916 LIST_INIT(&node->list);
2917 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2918 }
2919
Willy Tarreau62a61232013-04-12 18:13:46 +02002920 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2921 if (curproxy->conf.uniqueid_format_string)
2922 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2923
Dragan Dosen43885c72015-10-01 13:18:13 +02002924 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002925
Willy Tarreau62a61232013-04-12 18:13:46 +02002926 if (defproxy.conf.uif_file) {
2927 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2928 curproxy->conf.uif_line = defproxy.conf.uif_line;
2929 }
William Lallemanda73203e2012-03-12 12:48:57 +01002930
2931 /* copy default header unique id */
2932 if (defproxy.header_unique_id)
2933 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2934
William Lallemand82fe75c2012-10-23 10:25:10 +02002935 /* default compression options */
2936 if (defproxy.comp != NULL) {
2937 curproxy->comp = calloc(1, sizeof(struct comp));
2938 curproxy->comp->algos = defproxy.comp->algos;
2939 curproxy->comp->types = defproxy.comp->types;
2940 }
2941
Willy Tarreaubaaee002006-06-26 02:48:02 +02002942 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002943 curproxy->conf.used_listener_id = EB_ROOT;
2944 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002945
Simon Horman98637e52014-06-20 12:30:16 +09002946 if (defproxy.check_path)
2947 curproxy->check_path = strdup(defproxy.check_path);
2948 if (defproxy.check_command)
2949 curproxy->check_command = strdup(defproxy.check_command);
2950
Simon Horman9dc49962015-01-30 11:22:59 +09002951 if (defproxy.email_alert.mailers.name)
2952 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2953 if (defproxy.email_alert.from)
2954 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2955 if (defproxy.email_alert.to)
2956 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2957 if (defproxy.email_alert.myhostname)
2958 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002959 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002960 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002961
Willy Tarreau93893792009-07-23 13:19:11 +02002962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002963 }
2964 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2965 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002966 /* FIXME-20070101: we should do this too at the end of the
2967 * config parsing to free all default values.
2968 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002969 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2970 err_code |= ERR_ABORT;
2971 goto out;
2972 }
2973
Willy Tarreaua534fea2008-08-03 12:19:50 +02002974 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002975 free(defproxy.check_command);
2976 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002977 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002978 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002979 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002980 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002981 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002982 free(defproxy.capture_name);
2983 free(defproxy.monitor_uri);
2984 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002985 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002986 free(defproxy.fwdfor_hdr_name);
2987 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002988 free(defproxy.orgto_hdr_name);
2989 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002990 free(defproxy.server_id_hdr_name);
2991 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002992 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002993 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002994 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002995 free(defproxy.expect_regex);
2996 defproxy.expect_regex = NULL;
2997 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002998
Willy Tarreau62a61232013-04-12 18:13:46 +02002999 if (defproxy.conf.logformat_string != default_http_log_format &&
3000 defproxy.conf.logformat_string != default_tcp_log_format &&
3001 defproxy.conf.logformat_string != clf_http_log_format)
3002 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02003003
Willy Tarreau62a61232013-04-12 18:13:46 +02003004 free(defproxy.conf.uniqueid_format_string);
3005 free(defproxy.conf.lfs_file);
3006 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02003007 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09003008 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02003009
Dragan Dosen0b85ece2015-09-25 19:17:44 +02003010 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
3011 free(defproxy.conf.logformat_sd_string);
3012 free(defproxy.conf.lfsd_file);
3013
Willy Tarreaua534fea2008-08-03 12:19:50 +02003014 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003015 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01003016
Willy Tarreaubaaee002006-06-26 02:48:02 +02003017 /* we cannot free uri_auth because it might already be used */
3018 init_default_instance();
3019 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003020 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
3021 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003022 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02003023 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003024 }
3025 else if (curproxy == NULL) {
3026 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003027 err_code |= ERR_ALERT | ERR_FATAL;
3028 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003029 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003030
3031 /* update the current file and line being parsed */
3032 curproxy->conf.args.file = curproxy->conf.file;
3033 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003034
3035 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02003036 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
3037 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
3038 if (err_code & ERR_FATAL)
3039 goto out;
3040 }
3041 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003042 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003043 int cur_arg;
3044
Willy Tarreaubaaee002006-06-26 02:48:02 +02003045 if (curproxy == &defproxy) {
3046 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003047 err_code |= ERR_ALERT | ERR_FATAL;
3048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003049 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003050 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003051 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052
Willy Tarreau24709282013-03-10 21:32:12 +01003053 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003054 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003055 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003056 err_code |= ERR_ALERT | ERR_FATAL;
3057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003059
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003060 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003061
3062 /* use default settings for unix sockets */
3063 bind_conf->ux.uid = global.unix_bind.ux.uid;
3064 bind_conf->ux.gid = global.unix_bind.ux.gid;
3065 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003066
3067 /* NOTE: the following line might create several listeners if there
3068 * are comma-separated IPs or port ranges. So all further processing
3069 * will have to be applied to all listeners created after last_listen.
3070 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003071 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3072 if (errmsg && *errmsg) {
3073 indent_msg(&errmsg, 2);
3074 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003075 }
3076 else
3077 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3078 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
3081 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003082
Willy Tarreau4348fad2012-09-20 16:48:07 +02003083 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3084 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003085 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003086 }
3087
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003088 cur_arg = 2;
3089 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003090 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003091 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003092 char *err;
3093
Willy Tarreau26982662012-09-12 23:17:10 +02003094 kw = bind_find_kw(args[cur_arg]);
3095 if (kw) {
3096 char *err = NULL;
3097 int code;
3098
3099 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003100 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3101 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003102 cur_arg += 1 + kw->skip ;
3103 err_code |= ERR_ALERT | ERR_FATAL;
3104 goto out;
3105 }
3106
Willy Tarreau4348fad2012-09-20 16:48:07 +02003107 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003108 err_code |= code;
3109
3110 if (code) {
3111 if (err && *err) {
3112 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003113 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003114 }
3115 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003116 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3117 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003118 if (code & ERR_FATAL) {
3119 free(err);
3120 cur_arg += 1 + kw->skip;
3121 goto out;
3122 }
3123 }
3124 free(err);
3125 cur_arg += 1 + kw->skip;
3126 continue;
3127 }
3128
Willy Tarreau8638f482012-09-18 18:01:17 +02003129 err = NULL;
3130 if (!bind_dumped) {
3131 bind_dump_kws(&err);
3132 indent_msg(&err, 4);
3133 bind_dumped = 1;
3134 }
3135
3136 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3137 file, linenum, args[0], args[1], args[cur_arg],
3138 err ? " Registered keywords :" : "", err ? err : "");
3139 free(err);
3140
Willy Tarreau93893792009-07-23 13:19:11 +02003141 err_code |= ERR_ALERT | ERR_FATAL;
3142 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003143 }
Willy Tarreau93893792009-07-23 13:19:11 +02003144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145 }
3146 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003147 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3149 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003150 err_code |= ERR_ALERT | ERR_FATAL;
3151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003152 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003153 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003154 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003155
Willy Tarreaubaaee002006-06-26 02:48:02 +02003156 /* flush useless bits */
3157 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003159 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003160 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003161 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003162 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003163
William Lallemanddf1425a2015-04-28 20:17:49 +02003164 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3165 goto out;
3166
Willy Tarreau1c47f852006-07-09 08:22:27 +02003167 if (!*args[1]) {
3168 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3169 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003170 err_code |= ERR_ALERT | ERR_FATAL;
3171 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003172 }
3173
Willy Tarreaua534fea2008-08-03 12:19:50 +02003174 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003175 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003176 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003177 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003178 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3179
Willy Tarreau93893792009-07-23 13:19:11 +02003180 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003181 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003182 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003183 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3184 goto out;
3185
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3187 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3188 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3189 else {
3190 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003191 err_code |= ERR_ALERT | ERR_FATAL;
3192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003193 }
3194 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003195 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003196 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003197
3198 if (curproxy == &defproxy) {
3199 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3200 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003201 err_code |= ERR_ALERT | ERR_FATAL;
3202 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003203 }
3204
William Lallemanddf1425a2015-04-28 20:17:49 +02003205 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3206 goto out;
3207
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003208 if (!*args[1]) {
3209 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3210 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003213 }
3214
3215 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003216 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003217 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003218
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003219 if (curproxy->uuid <= 0) {
3220 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003221 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003222 err_code |= ERR_ALERT | ERR_FATAL;
3223 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003224 }
3225
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003226 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3227 if (node) {
3228 struct proxy *target = container_of(node, struct proxy, conf.id);
3229 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3230 file, linenum, proxy_type_str(curproxy), curproxy->id,
3231 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3232 err_code |= ERR_ALERT | ERR_FATAL;
3233 goto out;
3234 }
3235 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003236 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003237 else if (!strcmp(args[0], "description")) {
3238 int i, len=0;
3239 char *d;
3240
Cyril Bonté99ed3272010-01-24 23:29:44 +01003241 if (curproxy == &defproxy) {
3242 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3243 file, linenum, args[0]);
3244 err_code |= ERR_ALERT | ERR_FATAL;
3245 goto out;
3246 }
3247
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003248 if (!*args[1]) {
3249 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3250 file, linenum, args[0]);
3251 return -1;
3252 }
3253
Willy Tarreau348acfe2014-04-14 15:00:39 +02003254 for (i = 1; *args[i]; i++)
3255 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003256
3257 d = (char *)calloc(1, len);
3258 curproxy->desc = d;
3259
Willy Tarreau348acfe2014-04-14 15:00:39 +02003260 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3261 for (i = 2; *args[i]; i++)
3262 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003263
3264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003265 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003266 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 curproxy->state = PR_STSTOPPED;
3269 }
3270 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003271 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273 curproxy->state = PR_STNEW;
3274 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003275 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3276 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003277 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003278
3279 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003280 unsigned int low, high;
3281
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003282 if (strcmp(args[cur_arg], "all") == 0) {
3283 set = 0;
3284 break;
3285 }
3286 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003287 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003288 }
3289 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003290 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003291 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003292 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003293 char *dash = strchr(args[cur_arg], '-');
3294
3295 low = high = str2uic(args[cur_arg]);
3296 if (dash)
3297 high = str2uic(dash + 1);
3298
3299 if (high < low) {
3300 unsigned int swap = low;
3301 low = high;
3302 high = swap;
3303 }
3304
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003305 if (low < 1 || high > LONGBITS) {
3306 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3307 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_ALERT | ERR_FATAL;
3309 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003310 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003311 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003312 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003313 }
3314 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003315 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3316 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003317 err_code |= ERR_ALERT | ERR_FATAL;
3318 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003319 }
3320 cur_arg++;
3321 }
3322 curproxy->bind_proc = set;
3323 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003324 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003325 if (curproxy == &defproxy) {
3326 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003327 err_code |= ERR_ALERT | ERR_FATAL;
3328 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003329 }
3330
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003331 err = invalid_char(args[1]);
3332 if (err) {
3333 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3334 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003335 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003336 }
3337
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003338 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003339 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3340 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003341 err_code |= ERR_ALERT | ERR_FATAL;
3342 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003343 }
3344 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003345 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3346 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347
Willy Tarreau977b8e42006-12-29 14:19:17 +01003348 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003349 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003350
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 if (*(args[1]) == 0) {
3352 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3353 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003354 err_code |= ERR_ALERT | ERR_FATAL;
3355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003357
Willy Tarreau67402132012-05-31 20:40:20 +02003358 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003359 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003360 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003361 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003362 curproxy->cookie_name = strdup(args[1]);
3363 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003364
Willy Tarreaubaaee002006-06-26 02:48:02 +02003365 cur_arg = 2;
3366 while (*(args[cur_arg])) {
3367 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003368 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369 }
3370 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003371 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003372 }
3373 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003374 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375 }
3376 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003377 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 }
3379 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003380 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003381 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003382 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003383 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003384 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003386 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003387 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003388 else if (!strcmp(args[cur_arg], "httponly")) {
3389 curproxy->ck_opts |= PR_CK_HTTPONLY;
3390 }
3391 else if (!strcmp(args[cur_arg], "secure")) {
3392 curproxy->ck_opts |= PR_CK_SECURE;
3393 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003394 else if (!strcmp(args[cur_arg], "domain")) {
3395 if (!*args[cur_arg + 1]) {
3396 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3397 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003398 err_code |= ERR_ALERT | ERR_FATAL;
3399 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003400 }
3401
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003402 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003403 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003404 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3405 " dots nor does not start with a dot."
3406 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003407 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003408 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003409 }
3410
3411 err = invalid_domainchar(args[cur_arg + 1]);
3412 if (err) {
3413 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3414 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003415 err_code |= ERR_ALERT | ERR_FATAL;
3416 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003417 }
3418
Willy Tarreau68a897b2009-12-03 23:28:34 +01003419 if (!curproxy->cookie_domain) {
3420 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3421 } else {
3422 /* one domain was already specified, add another one by
3423 * building the string which will be returned along with
3424 * the cookie.
3425 */
3426 char *new_ptr;
3427 int new_len = strlen(curproxy->cookie_domain) +
3428 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3429 new_ptr = malloc(new_len);
3430 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3431 free(curproxy->cookie_domain);
3432 curproxy->cookie_domain = new_ptr;
3433 }
Willy Tarreau31936852010-10-06 16:59:56 +02003434 cur_arg++;
3435 }
3436 else if (!strcmp(args[cur_arg], "maxidle")) {
3437 unsigned int maxidle;
3438 const char *res;
3439
3440 if (!*args[cur_arg + 1]) {
3441 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3442 file, linenum, args[cur_arg]);
3443 err_code |= ERR_ALERT | ERR_FATAL;
3444 goto out;
3445 }
3446
3447 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3448 if (res) {
3449 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3450 file, linenum, *res, args[cur_arg]);
3451 err_code |= ERR_ALERT | ERR_FATAL;
3452 goto out;
3453 }
3454 curproxy->cookie_maxidle = maxidle;
3455 cur_arg++;
3456 }
3457 else if (!strcmp(args[cur_arg], "maxlife")) {
3458 unsigned int maxlife;
3459 const char *res;
3460
3461 if (!*args[cur_arg + 1]) {
3462 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3463 file, linenum, args[cur_arg]);
3464 err_code |= ERR_ALERT | ERR_FATAL;
3465 goto out;
3466 }
3467
3468 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3469 if (res) {
3470 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3471 file, linenum, *res, args[cur_arg]);
3472 err_code |= ERR_ALERT | ERR_FATAL;
3473 goto out;
3474 }
3475 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003476 cur_arg++;
3477 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003478 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003479 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 +02003480 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003481 err_code |= ERR_ALERT | ERR_FATAL;
3482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003483 }
3484 cur_arg++;
3485 }
Willy Tarreau67402132012-05-31 20:40:20 +02003486 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003487 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3488 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003489 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003490 }
3491
Willy Tarreau67402132012-05-31 20:40:20 +02003492 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003493 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3494 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003495 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003496 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003497
Willy Tarreau67402132012-05-31 20:40:20 +02003498 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003499 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3500 file, linenum);
3501 err_code |= ERR_ALERT | ERR_FATAL;
3502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003503 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003504 else if (!strcmp(args[0], "email-alert")) {
3505 if (*(args[1]) == 0) {
3506 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3507 file, linenum, args[0]);
3508 err_code |= ERR_ALERT | ERR_FATAL;
3509 goto out;
3510 }
3511
3512 if (!strcmp(args[1], "from")) {
3513 if (*(args[1]) == 0) {
3514 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3515 file, linenum, args[1]);
3516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
3518 }
3519 free(curproxy->email_alert.from);
3520 curproxy->email_alert.from = strdup(args[2]);
3521 }
3522 else if (!strcmp(args[1], "mailers")) {
3523 if (*(args[1]) == 0) {
3524 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3525 file, linenum, args[1]);
3526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
3528 }
3529 free(curproxy->email_alert.mailers.name);
3530 curproxy->email_alert.mailers.name = strdup(args[2]);
3531 }
3532 else if (!strcmp(args[1], "myhostname")) {
3533 if (*(args[1]) == 0) {
3534 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3535 file, linenum, args[1]);
3536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
3538 }
3539 free(curproxy->email_alert.myhostname);
3540 curproxy->email_alert.myhostname = strdup(args[2]);
3541 }
Simon Horman64e34162015-02-06 11:11:57 +09003542 else if (!strcmp(args[1], "level")) {
3543 curproxy->email_alert.level = get_log_level(args[2]);
3544 if (curproxy->email_alert.level < 0) {
3545 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3546 file, linenum, args[1], args[2]);
3547 err_code |= ERR_ALERT | ERR_FATAL;
3548 goto out;
3549 }
3550 }
Simon Horman9dc49962015-01-30 11:22:59 +09003551 else if (!strcmp(args[1], "to")) {
3552 if (*(args[1]) == 0) {
3553 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3554 file, linenum, args[1]);
3555 err_code |= ERR_ALERT | ERR_FATAL;
3556 goto out;
3557 }
3558 free(curproxy->email_alert.to);
3559 curproxy->email_alert.to = strdup(args[2]);
3560 }
3561 else {
3562 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3563 file, linenum, args[1]);
3564 err_code |= ERR_ALERT | ERR_FATAL;
3565 goto out;
3566 }
Simon Horman64e34162015-02-06 11:11:57 +09003567 /* Indicate that the email_alert is at least partially configured */
3568 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003569 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003570 else if (!strcmp(args[0], "external-check")) {
3571 if (*(args[1]) == 0) {
3572 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3573 file, linenum, args[0]);
3574 err_code |= ERR_ALERT | ERR_FATAL;
3575 goto out;
3576 }
3577
3578 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003579 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003580 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003581 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003582 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3583 file, linenum, args[1]);
3584 err_code |= ERR_ALERT | ERR_FATAL;
3585 goto out;
3586 }
3587 free(curproxy->check_command);
3588 curproxy->check_command = strdup(args[2]);
3589 }
3590 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003591 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003592 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003593 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003594 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3595 file, linenum, args[1]);
3596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
3598 }
3599 free(curproxy->check_path);
3600 curproxy->check_path = strdup(args[2]);
3601 }
3602 else {
3603 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3604 file, linenum, args[1]);
3605 err_code |= ERR_ALERT | ERR_FATAL;
3606 goto out;
3607 }
3608 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003609 else if (!strcmp(args[0], "persist")) { /* persist */
3610 if (*(args[1]) == 0) {
3611 Alert("parsing [%s:%d] : missing persist method.\n",
3612 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003615 }
3616
3617 if (!strncmp(args[1], "rdp-cookie", 10)) {
3618 curproxy->options2 |= PR_O2_RDPC_PRST;
3619
Emeric Brunb982a3d2010-01-04 15:45:53 +01003620 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003621 const char *beg, *end;
3622
3623 beg = args[1] + 11;
3624 end = strchr(beg, ')');
3625
William Lallemanddf1425a2015-04-28 20:17:49 +02003626 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3627 goto out;
3628
Emeric Brun647caf12009-06-30 17:57:00 +02003629 if (!end || end == beg) {
3630 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3631 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003632 err_code |= ERR_ALERT | ERR_FATAL;
3633 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003634 }
3635
3636 free(curproxy->rdp_cookie_name);
3637 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3638 curproxy->rdp_cookie_len = end-beg;
3639 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003640 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003641 free(curproxy->rdp_cookie_name);
3642 curproxy->rdp_cookie_name = strdup("msts");
3643 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3644 }
3645 else { /* syntax */
3646 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3647 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003648 err_code |= ERR_ALERT | ERR_FATAL;
3649 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003650 }
3651 }
3652 else {
3653 Alert("parsing [%s:%d] : unknown persist method.\n",
3654 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003655 err_code |= ERR_ALERT | ERR_FATAL;
3656 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003657 }
3658 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003659 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003660 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3661 err_code |= ERR_ALERT | ERR_FATAL;
3662 goto out;
3663 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003664 else if (!strcmp(args[0], "load-server-state-from-file")) {
3665 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3666 err_code |= ERR_WARN;
3667 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3668 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3669 }
3670 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3671 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3672 }
3673 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3674 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3675 }
3676 else {
3677 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3678 file, linenum, args[0], args[1]);
3679 err_code |= ERR_ALERT | ERR_FATAL;
3680 goto out;
3681 }
3682 }
3683 else if (!strcmp(args[0], "server-state-file-name")) {
3684 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3685 err_code |= ERR_WARN;
3686 if (*(args[1]) == 0) {
3687 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3688 file, linenum, args[0]);
3689 err_code |= ERR_ALERT | ERR_FATAL;
3690 goto out;
3691 }
3692 else if (!strcmp(args[1], "use-backend-name"))
3693 curproxy->server_state_file_name = strdup(curproxy->id);
3694 else
3695 curproxy->server_state_file_name = strdup(args[1]);
3696 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003698 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003699 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003700
Willy Tarreaubaaee002006-06-26 02:48:02 +02003701 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003702 if (curproxy == &defproxy) {
3703 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3704 err_code |= ERR_ALERT | ERR_FATAL;
3705 goto out;
3706 }
3707
William Lallemand1a748ae2015-05-19 16:37:23 +02003708 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3709 goto out;
3710
Willy Tarreaubaaee002006-06-26 02:48:02 +02003711 if (*(args[4]) == 0) {
3712 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3713 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003716 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003717 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003718 curproxy->capture_name = strdup(args[2]);
3719 curproxy->capture_namelen = strlen(curproxy->capture_name);
3720 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 curproxy->to_log |= LW_COOKIE;
3722 }
3723 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3724 struct cap_hdr *hdr;
3725
3726 if (curproxy == &defproxy) {
3727 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 +02003728 err_code |= ERR_ALERT | ERR_FATAL;
3729 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003730 }
3731
William Lallemand1a748ae2015-05-19 16:37:23 +02003732 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3733 goto out;
3734
Willy Tarreaubaaee002006-06-26 02:48:02 +02003735 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3736 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3737 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003738 err_code |= ERR_ALERT | ERR_FATAL;
3739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003740 }
3741
3742 hdr = calloc(sizeof(struct cap_hdr), 1);
3743 hdr->next = curproxy->req_cap;
3744 hdr->name = strdup(args[3]);
3745 hdr->namelen = strlen(args[3]);
3746 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003747 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003748 hdr->index = curproxy->nb_req_cap++;
3749 curproxy->req_cap = hdr;
3750 curproxy->to_log |= LW_REQHDR;
3751 }
3752 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3753 struct cap_hdr *hdr;
3754
3755 if (curproxy == &defproxy) {
3756 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 +02003757 err_code |= ERR_ALERT | ERR_FATAL;
3758 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003759 }
3760
William Lallemand1a748ae2015-05-19 16:37:23 +02003761 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3762 goto out;
3763
Willy Tarreaubaaee002006-06-26 02:48:02 +02003764 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3765 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3766 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003769 }
3770 hdr = calloc(sizeof(struct cap_hdr), 1);
3771 hdr->next = curproxy->rsp_cap;
3772 hdr->name = strdup(args[3]);
3773 hdr->namelen = strlen(args[3]);
3774 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003775 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776 hdr->index = curproxy->nb_rsp_cap++;
3777 curproxy->rsp_cap = hdr;
3778 curproxy->to_log |= LW_RSPHDR;
3779 }
3780 else {
3781 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3782 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003783 err_code |= ERR_ALERT | ERR_FATAL;
3784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003785 }
3786 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003787 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003788 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003789 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003790
William Lallemanddf1425a2015-04-28 20:17:49 +02003791 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3792 goto out;
3793
Willy Tarreaubaaee002006-06-26 02:48:02 +02003794 if (*(args[1]) == 0) {
3795 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3796 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003797 err_code |= ERR_ALERT | ERR_FATAL;
3798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003799 }
3800 curproxy->conn_retries = atol(args[1]);
3801 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003802 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003803 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003804
3805 if (curproxy == &defproxy) {
3806 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
3809 }
3810
Willy Tarreau20b0de52012-12-24 15:45:22 +01003811 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003812 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003813 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3814 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3815 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3816 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003817 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 +01003818 file, linenum, args[0]);
3819 err_code |= ERR_WARN;
3820 }
3821
Willy Tarreauff011f22011-01-06 17:51:27 +01003822 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003823
Willy Tarreauff011f22011-01-06 17:51:27 +01003824 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003825 err_code |= ERR_ALERT | ERR_ABORT;
3826 goto out;
3827 }
3828
Willy Tarreau5002f572014-04-23 01:32:02 +02003829 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003830 err_code |= warnif_cond_conflicts(rule->cond,
3831 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3832 file, linenum);
3833
Willy Tarreauff011f22011-01-06 17:51:27 +01003834 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003835 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003836 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003837 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003838
3839 if (curproxy == &defproxy) {
3840 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3841 err_code |= ERR_ALERT | ERR_FATAL;
3842 goto out;
3843 }
3844
3845 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003846 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003847 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3848 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003849 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3850 file, linenum, args[0]);
3851 err_code |= ERR_WARN;
3852 }
3853
3854 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3855
3856 if (!rule) {
3857 err_code |= ERR_ALERT | ERR_ABORT;
3858 goto out;
3859 }
3860
3861 err_code |= warnif_cond_conflicts(rule->cond,
3862 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3863 file, linenum);
3864
3865 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3866 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003867 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3868 /* set the header name and length into the proxy structure */
3869 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3870 err_code |= ERR_WARN;
3871
3872 if (!*args[1]) {
3873 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3874 file, linenum, args[0]);
3875 err_code |= ERR_ALERT | ERR_FATAL;
3876 goto out;
3877 }
3878
3879 /* set the desired header name */
3880 free(curproxy->server_id_hdr_name);
3881 curproxy->server_id_hdr_name = strdup(args[1]);
3882 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3883 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003884 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003885 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003886
Willy Tarreaub099aca2008-10-12 17:26:37 +02003887 if (curproxy == &defproxy) {
3888 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003889 err_code |= ERR_ALERT | ERR_FATAL;
3890 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003891 }
3892
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003893 /* emulate "block" using "http-request block". Since these rules are supposed to
3894 * be processed before all http-request rules, we put them into their own list
3895 * and will insert them at the end.
3896 */
3897 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3898 if (!rule) {
3899 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003900 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003901 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003902 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3903 err_code |= warnif_cond_conflicts(rule->cond,
3904 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3905 file, linenum);
3906 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003907
3908 if (!already_warned(WARN_BLOCK_DEPRECATED))
3909 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]);
3910
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003911 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003912 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003913 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003914
Cyril Bonté99ed3272010-01-24 23:29:44 +01003915 if (curproxy == &defproxy) {
3916 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
3919 }
3920
Willy Tarreaube4653b2015-05-28 15:26:58 +02003921 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003922 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3923 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003924 err_code |= ERR_ALERT | ERR_FATAL;
3925 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003926 }
3927
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003928 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003929 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003930 err_code |= warnif_cond_conflicts(rule->cond,
3931 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3932 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003933 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003934 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003935 struct switching_rule *rule;
3936
Willy Tarreaub099aca2008-10-12 17:26:37 +02003937 if (curproxy == &defproxy) {
3938 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003941 }
3942
Willy Tarreau55ea7572007-06-17 19:56:27 +02003943 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003944 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003945
3946 if (*(args[1]) == 0) {
3947 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003950 }
3951
Willy Tarreauf51658d2014-04-23 01:21:56 +02003952 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3953 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3954 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3955 file, linenum, errmsg);
3956 err_code |= ERR_ALERT | ERR_FATAL;
3957 goto out;
3958 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003959
Willy Tarreauf51658d2014-04-23 01:21:56 +02003960 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003961 }
3962
3963 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3964 rule->cond = cond;
3965 rule->be.name = strdup(args[1]);
3966 LIST_INIT(&rule->list);
3967 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3968 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003969 else if (strcmp(args[0], "use-server") == 0) {
3970 struct server_rule *rule;
3971
3972 if (curproxy == &defproxy) {
3973 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3974 err_code |= ERR_ALERT | ERR_FATAL;
3975 goto out;
3976 }
3977
3978 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3979 err_code |= ERR_WARN;
3980
3981 if (*(args[1]) == 0) {
3982 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3983 err_code |= ERR_ALERT | ERR_FATAL;
3984 goto out;
3985 }
3986
3987 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3988 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3989 file, linenum, args[0]);
3990 err_code |= ERR_ALERT | ERR_FATAL;
3991 goto out;
3992 }
3993
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003994 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3995 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3996 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
3999 }
4000
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004001 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004002
4003 rule = (struct server_rule *)calloc(1, sizeof(*rule));
4004 rule->cond = cond;
4005 rule->srv.name = strdup(args[1]);
4006 LIST_INIT(&rule->list);
4007 LIST_ADDQ(&curproxy->server_rules, &rule->list);
4008 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
4009 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004010 else if ((!strcmp(args[0], "force-persist")) ||
4011 (!strcmp(args[0], "ignore-persist"))) {
4012 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01004013
4014 if (curproxy == &defproxy) {
4015 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4016 err_code |= ERR_ALERT | ERR_FATAL;
4017 goto out;
4018 }
4019
4020 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
4021 err_code |= ERR_WARN;
4022
Willy Tarreauef6494c2010-01-28 17:12:36 +01004023 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01004024 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4025 file, linenum, args[0]);
4026 err_code |= ERR_ALERT | ERR_FATAL;
4027 goto out;
4028 }
4029
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004030 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
4031 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
4032 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01004033 err_code |= ERR_ALERT | ERR_FATAL;
4034 goto out;
4035 }
4036
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004037 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
4038 * where force-persist is applied.
4039 */
4040 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01004041
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004042 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01004043 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004044 if (!strcmp(args[0], "force-persist")) {
4045 rule->type = PERSIST_TYPE_FORCE;
4046 } else {
4047 rule->type = PERSIST_TYPE_IGNORE;
4048 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004049 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004050 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004051 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004052 else if (!strcmp(args[0], "stick-table")) {
4053 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004054 struct proxy *other;
4055
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004056 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004057 if (other) {
4058 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4059 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
4062 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004063
Emeric Brun32da3c42010-09-23 18:39:19 +02004064 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004065 curproxy->table.type = (unsigned int)-1;
4066 while (*args[myidx]) {
4067 const char *err;
4068
4069 if (strcmp(args[myidx], "size") == 0) {
4070 myidx++;
4071 if (!*(args[myidx])) {
4072 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4073 file, linenum, args[myidx-1]);
4074 err_code |= ERR_ALERT | ERR_FATAL;
4075 goto out;
4076 }
4077 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4078 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4079 file, linenum, *err, args[myidx-1]);
4080 err_code |= ERR_ALERT | ERR_FATAL;
4081 goto out;
4082 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004083 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004084 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004085 else if (strcmp(args[myidx], "peers") == 0) {
4086 myidx++;
Godbach50523162013-12-11 19:48:57 +08004087 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004088 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4089 file, linenum, args[myidx-1]);
4090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
Godbach50523162013-12-11 19:48:57 +08004092 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004093 curproxy->table.peers.name = strdup(args[myidx++]);
4094 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004095 else if (strcmp(args[myidx], "expire") == 0) {
4096 myidx++;
4097 if (!*(args[myidx])) {
4098 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4099 file, linenum, args[myidx-1]);
4100 err_code |= ERR_ALERT | ERR_FATAL;
4101 goto out;
4102 }
4103 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4104 if (err) {
4105 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4106 file, linenum, *err, args[myidx-1]);
4107 err_code |= ERR_ALERT | ERR_FATAL;
4108 goto out;
4109 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004110 if (val > INT_MAX) {
4111 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4112 file, linenum, val);
4113 err_code |= ERR_ALERT | ERR_FATAL;
4114 goto out;
4115 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004116 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004117 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004118 }
4119 else if (strcmp(args[myidx], "nopurge") == 0) {
4120 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004121 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004122 }
4123 else if (strcmp(args[myidx], "type") == 0) {
4124 myidx++;
4125 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4126 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4127 file, linenum, args[myidx]);
4128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
4130 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004131 /* myidx already points to next arg */
4132 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004133 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004134 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004135 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004136
4137 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004138 nw = args[myidx];
4139 while (*nw) {
4140 /* the "store" keyword supports a comma-separated list */
4141 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004142 sa = NULL; /* store arg */
4143 while (*nw && *nw != ',') {
4144 if (*nw == '(') {
4145 *nw = 0;
4146 sa = ++nw;
4147 while (*nw != ')') {
4148 if (!*nw) {
4149 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4150 file, linenum, args[0], cw);
4151 err_code |= ERR_ALERT | ERR_FATAL;
4152 goto out;
4153 }
4154 nw++;
4155 }
4156 *nw = '\0';
4157 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004158 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004159 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004160 if (*nw)
4161 *nw++ = '\0';
4162 type = stktable_get_data_type(cw);
4163 if (type < 0) {
4164 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4165 file, linenum, args[0], cw);
4166 err_code |= ERR_ALERT | ERR_FATAL;
4167 goto out;
4168 }
Willy Tarreauac782882010-06-20 10:41:54 +02004169
4170 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4171 switch (err) {
4172 case PE_NONE: break;
4173 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004174 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4175 file, linenum, args[0], cw);
4176 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004177 break;
4178
4179 case PE_ARG_MISSING:
4180 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4181 file, linenum, args[0], cw);
4182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
4184
4185 case PE_ARG_NOT_USED:
4186 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4187 file, linenum, args[0], cw);
4188 err_code |= ERR_ALERT | ERR_FATAL;
4189 goto out;
4190
4191 default:
4192 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4193 file, linenum, args[0], cw);
4194 err_code |= ERR_ALERT | ERR_FATAL;
4195 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004196 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004197 }
4198 myidx++;
4199 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004200 else {
4201 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4202 file, linenum, args[myidx]);
4203 err_code |= ERR_ALERT | ERR_FATAL;
4204 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004205 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004206 }
4207
4208 if (!curproxy->table.size) {
4209 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4210 file, linenum);
4211 err_code |= ERR_ALERT | ERR_FATAL;
4212 goto out;
4213 }
4214
4215 if (curproxy->table.type == (unsigned int)-1) {
4216 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4217 file, linenum);
4218 err_code |= ERR_ALERT | ERR_FATAL;
4219 goto out;
4220 }
4221 }
4222 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004223 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004224 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004225 int myidx = 0;
4226 const char *name = NULL;
4227 int flags;
4228
4229 if (curproxy == &defproxy) {
4230 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4231 err_code |= ERR_ALERT | ERR_FATAL;
4232 goto out;
4233 }
4234
4235 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4236 err_code |= ERR_WARN;
4237 goto out;
4238 }
4239
4240 myidx++;
4241 if ((strcmp(args[myidx], "store") == 0) ||
4242 (strcmp(args[myidx], "store-request") == 0)) {
4243 myidx++;
4244 flags = STK_IS_STORE;
4245 }
4246 else if (strcmp(args[myidx], "store-response") == 0) {
4247 myidx++;
4248 flags = STK_IS_STORE | STK_ON_RSP;
4249 }
4250 else if (strcmp(args[myidx], "match") == 0) {
4251 myidx++;
4252 flags = STK_IS_MATCH;
4253 }
4254 else if (strcmp(args[myidx], "on") == 0) {
4255 myidx++;
4256 flags = STK_IS_MATCH | STK_IS_STORE;
4257 }
4258 else {
4259 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4260 err_code |= ERR_ALERT | ERR_FATAL;
4261 goto out;
4262 }
4263
4264 if (*(args[myidx]) == 0) {
4265 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4266 err_code |= ERR_ALERT | ERR_FATAL;
4267 goto out;
4268 }
4269
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004270 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004271 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004272 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004273 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004274 err_code |= ERR_ALERT | ERR_FATAL;
4275 goto out;
4276 }
4277
4278 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004279 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4280 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4281 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004282 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004283 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004284 goto out;
4285 }
4286 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004287 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4288 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4289 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004290 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004291 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004292 goto out;
4293 }
4294 }
4295
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004296 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004297 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004298
Emeric Brunb982a3d2010-01-04 15:45:53 +01004299 if (strcmp(args[myidx], "table") == 0) {
4300 myidx++;
4301 name = args[myidx++];
4302 }
4303
Willy Tarreauef6494c2010-01-28 17:12:36 +01004304 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004305 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4306 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4307 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004308 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004309 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004310 goto out;
4311 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004312 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004313 else if (*(args[myidx])) {
4314 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4315 file, linenum, args[0], args[myidx]);
4316 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004317 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004318 goto out;
4319 }
Emeric Brun97679e72010-09-23 17:56:44 +02004320 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004321 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004322 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004323 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004324
Emeric Brunb982a3d2010-01-04 15:45:53 +01004325 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4326 rule->cond = cond;
4327 rule->expr = expr;
4328 rule->flags = flags;
4329 rule->table.name = name ? strdup(name) : NULL;
4330 LIST_INIT(&rule->list);
4331 if (flags & STK_ON_RSP)
4332 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4333 else
4334 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4335 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004336 else if (!strcmp(args[0], "stats")) {
4337 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4338 curproxy->uri_auth = NULL; /* we must detach from the default config */
4339
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004340 if (!*args[1]) {
4341 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004342 } else if (!strcmp(args[1], "admin")) {
4343 struct stats_admin_rule *rule;
4344
4345 if (curproxy == &defproxy) {
4346 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4347 err_code |= ERR_ALERT | ERR_FATAL;
4348 goto out;
4349 }
4350
4351 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4352 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4353 err_code |= ERR_ALERT | ERR_ABORT;
4354 goto out;
4355 }
4356
4357 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4358 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4359 file, linenum, args[0], args[1]);
4360 err_code |= ERR_ALERT | ERR_FATAL;
4361 goto out;
4362 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004363 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4364 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4365 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004366 err_code |= ERR_ALERT | ERR_FATAL;
4367 goto out;
4368 }
4369
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004370 err_code |= warnif_cond_conflicts(cond,
4371 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4372 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004373
4374 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4375 rule->cond = cond;
4376 LIST_INIT(&rule->list);
4377 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004378 } else if (!strcmp(args[1], "uri")) {
4379 if (*(args[2]) == 0) {
4380 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004381 err_code |= ERR_ALERT | ERR_FATAL;
4382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004383 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4384 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004385 err_code |= ERR_ALERT | ERR_ABORT;
4386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004387 }
4388 } else if (!strcmp(args[1], "realm")) {
4389 if (*(args[2]) == 0) {
4390 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004391 err_code |= ERR_ALERT | ERR_FATAL;
4392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004393 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4394 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004395 err_code |= ERR_ALERT | ERR_ABORT;
4396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004397 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004398 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004399 unsigned interval;
4400
4401 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4402 if (err) {
4403 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4404 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004405 err_code |= ERR_ALERT | ERR_FATAL;
4406 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004407 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4408 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004409 err_code |= ERR_ALERT | ERR_ABORT;
4410 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004411 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004412 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004413 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004414
4415 if (curproxy == &defproxy) {
4416 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4417 err_code |= ERR_ALERT | ERR_FATAL;
4418 goto out;
4419 }
4420
4421 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4422 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4423 err_code |= ERR_ALERT | ERR_ABORT;
4424 goto out;
4425 }
4426
Willy Tarreauff011f22011-01-06 17:51:27 +01004427 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004428 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004429 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4430 file, linenum, args[0]);
4431 err_code |= ERR_WARN;
4432 }
4433
Willy Tarreauff011f22011-01-06 17:51:27 +01004434 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004435
Willy Tarreauff011f22011-01-06 17:51:27 +01004436 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004437 err_code |= ERR_ALERT | ERR_ABORT;
4438 goto out;
4439 }
4440
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004441 err_code |= warnif_cond_conflicts(rule->cond,
4442 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4443 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004444 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004445
Willy Tarreaubaaee002006-06-26 02:48:02 +02004446 } else if (!strcmp(args[1], "auth")) {
4447 if (*(args[2]) == 0) {
4448 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004449 err_code |= ERR_ALERT | ERR_FATAL;
4450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004451 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4452 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004453 err_code |= ERR_ALERT | ERR_ABORT;
4454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004455 }
4456 } else if (!strcmp(args[1], "scope")) {
4457 if (*(args[2]) == 0) {
4458 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004459 err_code |= ERR_ALERT | ERR_FATAL;
4460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004461 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4462 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004463 err_code |= ERR_ALERT | ERR_ABORT;
4464 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004465 }
4466 } else if (!strcmp(args[1], "enable")) {
4467 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4468 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004469 err_code |= ERR_ALERT | ERR_ABORT;
4470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004471 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004472 } else if (!strcmp(args[1], "hide-version")) {
4473 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4474 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004475 err_code |= ERR_ALERT | ERR_ABORT;
4476 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004477 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004478 } else if (!strcmp(args[1], "show-legends")) {
4479 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4480 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4481 err_code |= ERR_ALERT | ERR_ABORT;
4482 goto out;
4483 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004484 } else if (!strcmp(args[1], "show-node")) {
4485
4486 if (*args[2]) {
4487 int i;
4488 char c;
4489
4490 for (i=0; args[2][i]; i++) {
4491 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004492 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4493 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004494 break;
4495 }
4496
4497 if (!i || args[2][i]) {
4498 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4499 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4500 file, linenum, args[0], args[1]);
4501 err_code |= ERR_ALERT | ERR_FATAL;
4502 goto out;
4503 }
4504 }
4505
4506 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4507 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4508 err_code |= ERR_ALERT | ERR_ABORT;
4509 goto out;
4510 }
4511 } else if (!strcmp(args[1], "show-desc")) {
4512 char *desc = NULL;
4513
4514 if (*args[2]) {
4515 int i, len=0;
4516 char *d;
4517
Willy Tarreau348acfe2014-04-14 15:00:39 +02004518 for (i = 2; *args[i]; i++)
4519 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004520
4521 desc = d = (char *)calloc(1, len);
4522
Willy Tarreau348acfe2014-04-14 15:00:39 +02004523 d += snprintf(d, desc + len - d, "%s", args[2]);
4524 for (i = 3; *args[i]; i++)
4525 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004526 }
4527
4528 if (!*args[2] && !global.desc)
4529 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4530 file, linenum, args[1]);
4531 else {
4532 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4533 free(desc);
4534 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4535 err_code |= ERR_ALERT | ERR_ABORT;
4536 goto out;
4537 }
4538 free(desc);
4539 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004540 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004541stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004542 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 +01004543 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004544 err_code |= ERR_ALERT | ERR_FATAL;
4545 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004546 }
4547 }
4548 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004549 int optnum;
4550
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004551 if (*(args[1]) == '\0') {
4552 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4553 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004554 err_code |= ERR_ALERT | ERR_FATAL;
4555 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004556 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004557
4558 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4559 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004560 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4561 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4562 file, linenum, cfg_opts[optnum].name);
4563 err_code |= ERR_ALERT | ERR_FATAL;
4564 goto out;
4565 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004566 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4567 goto out;
4568
Willy Tarreau93893792009-07-23 13:19:11 +02004569 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4570 err_code |= ERR_WARN;
4571 goto out;
4572 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004573
Willy Tarreau3842f002009-06-14 11:39:52 +02004574 curproxy->no_options &= ~cfg_opts[optnum].val;
4575 curproxy->options &= ~cfg_opts[optnum].val;
4576
4577 switch (kwm) {
4578 case KWM_STD:
4579 curproxy->options |= cfg_opts[optnum].val;
4580 break;
4581 case KWM_NO:
4582 curproxy->no_options |= cfg_opts[optnum].val;
4583 break;
4584 case KWM_DEF: /* already cleared */
4585 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004586 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004587
Willy Tarreau93893792009-07-23 13:19:11 +02004588 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004589 }
4590 }
4591
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004592 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4593 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004594 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4595 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4596 file, linenum, cfg_opts2[optnum].name);
4597 err_code |= ERR_ALERT | ERR_FATAL;
4598 goto out;
4599 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004600 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4601 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004602 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4603 err_code |= ERR_WARN;
4604 goto out;
4605 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004606
Willy Tarreau3842f002009-06-14 11:39:52 +02004607 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4608 curproxy->options2 &= ~cfg_opts2[optnum].val;
4609
4610 switch (kwm) {
4611 case KWM_STD:
4612 curproxy->options2 |= cfg_opts2[optnum].val;
4613 break;
4614 case KWM_NO:
4615 curproxy->no_options2 |= cfg_opts2[optnum].val;
4616 break;
4617 case KWM_DEF: /* already cleared */
4618 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004619 }
Willy Tarreau93893792009-07-23 13:19:11 +02004620 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004621 }
4622 }
4623
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004624 /* HTTP options override each other. They can be cancelled using
4625 * "no option xxx" which only switches to default mode if the mode
4626 * was this one (useful for cancelling options set in defaults
4627 * sections).
4628 */
4629 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004630 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4631 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004632 if (kwm == KWM_STD) {
4633 curproxy->options &= ~PR_O_HTTP_MODE;
4634 curproxy->options |= PR_O_HTTP_PCL;
4635 goto out;
4636 }
4637 else if (kwm == KWM_NO) {
4638 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4639 curproxy->options &= ~PR_O_HTTP_MODE;
4640 goto out;
4641 }
4642 }
4643 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004644 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4645 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004646 if (kwm == KWM_STD) {
4647 curproxy->options &= ~PR_O_HTTP_MODE;
4648 curproxy->options |= PR_O_HTTP_FCL;
4649 goto out;
4650 }
4651 else if (kwm == KWM_NO) {
4652 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4653 curproxy->options &= ~PR_O_HTTP_MODE;
4654 goto out;
4655 }
4656 }
4657 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004658 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4659 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004660 if (kwm == KWM_STD) {
4661 curproxy->options &= ~PR_O_HTTP_MODE;
4662 curproxy->options |= PR_O_HTTP_SCL;
4663 goto out;
4664 }
4665 else if (kwm == KWM_NO) {
4666 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4667 curproxy->options &= ~PR_O_HTTP_MODE;
4668 goto out;
4669 }
4670 }
4671 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004672 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4673 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004674 if (kwm == KWM_STD) {
4675 curproxy->options &= ~PR_O_HTTP_MODE;
4676 curproxy->options |= PR_O_HTTP_KAL;
4677 goto out;
4678 }
4679 else if (kwm == KWM_NO) {
4680 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4681 curproxy->options &= ~PR_O_HTTP_MODE;
4682 goto out;
4683 }
4684 }
4685 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004686 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4687 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004688 if (kwm == KWM_STD) {
4689 curproxy->options &= ~PR_O_HTTP_MODE;
4690 curproxy->options |= PR_O_HTTP_TUN;
4691 goto out;
4692 }
4693 else if (kwm == KWM_NO) {
4694 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4695 curproxy->options &= ~PR_O_HTTP_MODE;
4696 goto out;
4697 }
4698 }
4699
Joseph Lynch726ab712015-05-11 23:25:34 -07004700 /* Redispatch can take an integer argument that control when the
4701 * resispatch occurs. All values are relative to the retries option.
4702 * This can be cancelled using "no option xxx".
4703 */
4704 if (strcmp(args[1], "redispatch") == 0) {
4705 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4706 err_code |= ERR_WARN;
4707 goto out;
4708 }
4709
4710 curproxy->no_options &= ~PR_O_REDISP;
4711 curproxy->options &= ~PR_O_REDISP;
4712
4713 switch (kwm) {
4714 case KWM_STD:
4715 curproxy->options |= PR_O_REDISP;
4716 curproxy->redispatch_after = -1;
4717 if(*args[2]) {
4718 curproxy->redispatch_after = atol(args[2]);
4719 }
4720 break;
4721 case KWM_NO:
4722 curproxy->no_options |= PR_O_REDISP;
4723 curproxy->redispatch_after = 0;
4724 break;
4725 case KWM_DEF: /* already cleared */
4726 break;
4727 }
4728 goto out;
4729 }
4730
Willy Tarreau3842f002009-06-14 11:39:52 +02004731 if (kwm != KWM_STD) {
4732 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004733 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004734 err_code |= ERR_ALERT | ERR_FATAL;
4735 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004736 }
4737
Emeric Brun3a058f32009-06-30 18:26:00 +02004738 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004739 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004740 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004741 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004742 if (*(args[2]) != '\0') {
4743 if (!strcmp(args[2], "clf")) {
4744 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004745 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004746 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004747 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004748 err_code |= ERR_ALERT | ERR_FATAL;
4749 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004750 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004751 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4752 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004753 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004754 if (curproxy->conf.logformat_string != default_http_log_format &&
4755 curproxy->conf.logformat_string != default_tcp_log_format &&
4756 curproxy->conf.logformat_string != clf_http_log_format)
4757 free(curproxy->conf.logformat_string);
4758 curproxy->conf.logformat_string = logformat;
4759
4760 free(curproxy->conf.lfs_file);
4761 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4762 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004763 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004764 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004765 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004766 if (curproxy->conf.logformat_string != default_http_log_format &&
4767 curproxy->conf.logformat_string != default_tcp_log_format &&
4768 curproxy->conf.logformat_string != clf_http_log_format)
4769 free(curproxy->conf.logformat_string);
4770 curproxy->conf.logformat_string = default_tcp_log_format;
4771
4772 free(curproxy->conf.lfs_file);
4773 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4774 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004775
4776 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4777 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004778 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004779 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004780 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004781 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004782 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004783
William Lallemanddf1425a2015-04-28 20:17:49 +02004784 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4785 goto out;
4786
Willy Tarreau13943ab2006-12-31 00:24:10 +01004787 if (curproxy->cap & PR_CAP_FE)
4788 curproxy->options |= PR_O_TCP_CLI_KA;
4789 if (curproxy->cap & PR_CAP_BE)
4790 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004791 }
4792 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004793 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004794 err_code |= ERR_WARN;
4795
Willy Tarreaubaaee002006-06-26 02:48:02 +02004796 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004797 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004798 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004799 curproxy->options2 &= ~PR_O2_CHK_ANY;
4800 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004801 if (!*args[2]) { /* no argument */
4802 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4803 curproxy->check_len = strlen(DEF_CHECK_REQ);
4804 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004805 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004806 curproxy->check_req = (char *)malloc(reqlen);
4807 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004808 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004809 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004810 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004811 if (*args[4])
4812 reqlen += strlen(args[4]);
4813 else
4814 reqlen += strlen("HTTP/1.0");
4815
4816 curproxy->check_req = (char *)malloc(reqlen);
4817 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004818 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004819 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004820 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4821 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004822 }
4823 else if (!strcmp(args[1], "ssl-hello-chk")) {
4824 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004825 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004826 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004827
Willy Tarreaua534fea2008-08-03 12:19:50 +02004828 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004829 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004830 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004831 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004832
4833 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004835 }
Willy Tarreau23677902007-05-08 23:50:35 +02004836 else if (!strcmp(args[1], "smtpchk")) {
4837 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004838 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004839 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004840 curproxy->options2 &= ~PR_O2_CHK_ANY;
4841 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004842
4843 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4844 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4845 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4846 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4847 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4848 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4849 curproxy->check_req = (char *)malloc(reqlen);
4850 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4851 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4852 } else {
4853 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4854 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4855 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4856 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4857 }
4858 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004859 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4860 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004861 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004862 else if (!strcmp(args[1], "pgsql-check")) {
4863 /* use PostgreSQL request to check servers' health */
4864 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4865 err_code |= ERR_WARN;
4866
4867 free(curproxy->check_req);
4868 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004869 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004870 curproxy->options2 |= PR_O2_PGSQL_CHK;
4871
4872 if (*(args[2])) {
4873 int cur_arg = 2;
4874
4875 while (*(args[cur_arg])) {
4876 if (strcmp(args[cur_arg], "user") == 0) {
4877 char * packet;
4878 uint32_t packet_len;
4879 uint32_t pv;
4880
4881 /* suboption header - needs additional argument for it */
4882 if (*(args[cur_arg+1]) == 0) {
4883 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4884 file, linenum, args[0], args[1], args[cur_arg]);
4885 err_code |= ERR_ALERT | ERR_FATAL;
4886 goto out;
4887 }
4888
4889 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4890 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4891 pv = htonl(0x30000); /* protocol version 3.0 */
4892
4893 packet = (char*) calloc(1, packet_len);
4894
4895 memcpy(packet + 4, &pv, 4);
4896
4897 /* copy "user" */
4898 memcpy(packet + 8, "user", 4);
4899
4900 /* copy username */
4901 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4902
4903 free(curproxy->check_req);
4904 curproxy->check_req = packet;
4905 curproxy->check_len = packet_len;
4906
4907 packet_len = htonl(packet_len);
4908 memcpy(packet, &packet_len, 4);
4909 cur_arg += 2;
4910 } else {
4911 /* unknown suboption - catchall */
4912 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4913 file, linenum, args[0], args[1]);
4914 err_code |= ERR_ALERT | ERR_FATAL;
4915 goto out;
4916 }
4917 } /* end while loop */
4918 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004919 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4920 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004921 }
4922
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004923 else if (!strcmp(args[1], "redis-check")) {
4924 /* use REDIS PING request to check servers' health */
4925 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4926 err_code |= ERR_WARN;
4927
4928 free(curproxy->check_req);
4929 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004930 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004931 curproxy->options2 |= PR_O2_REDIS_CHK;
4932
4933 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4934 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4935 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004936
4937 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4938 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004939 }
4940
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004941 else if (!strcmp(args[1], "mysql-check")) {
4942 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004943 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4944 err_code |= ERR_WARN;
4945
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004946 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004947 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004948 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004949 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004950
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004951 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004952 * const char mysql40_client_auth_pkt[] = {
4953 * "\x0e\x00\x00" // packet length
4954 * "\x01" // packet number
4955 * "\x00\x00" // client capabilities
4956 * "\x00\x00\x01" // max packet
4957 * "haproxy\x00" // username (null terminated string)
4958 * "\x00" // filler (always 0x00)
4959 * "\x01\x00\x00" // packet length
4960 * "\x00" // packet number
4961 * "\x01" // COM_QUIT command
4962 * };
4963 */
4964
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004965 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4966 * const char mysql41_client_auth_pkt[] = {
4967 * "\x0e\x00\x00\" // packet length
4968 * "\x01" // packet number
4969 * "\x00\x00\x00\x00" // client capabilities
4970 * "\x00\x00\x00\x01" // max packet
4971 * "\x21" // character set (UTF-8)
4972 * char[23] // All zeroes
4973 * "haproxy\x00" // username (null terminated string)
4974 * "\x00" // filler (always 0x00)
4975 * "\x01\x00\x00" // packet length
4976 * "\x00" // packet number
4977 * "\x01" // COM_QUIT command
4978 * };
4979 */
4980
4981
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004982 if (*(args[2])) {
4983 int cur_arg = 2;
4984
4985 while (*(args[cur_arg])) {
4986 if (strcmp(args[cur_arg], "user") == 0) {
4987 char *mysqluser;
4988 int packetlen, reqlen, userlen;
4989
4990 /* suboption header - needs additional argument for it */
4991 if (*(args[cur_arg+1]) == 0) {
4992 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4993 file, linenum, args[0], args[1], args[cur_arg]);
4994 err_code |= ERR_ALERT | ERR_FATAL;
4995 goto out;
4996 }
4997 mysqluser = args[cur_arg + 1];
4998 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004999
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005000 if (*(args[cur_arg+2])) {
5001 if (!strcmp(args[cur_arg+2], "post-41")) {
5002 packetlen = userlen + 7 + 27;
5003 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005004
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005005 free(curproxy->check_req);
5006 curproxy->check_req = (char *)calloc(1, reqlen);
5007 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005008
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005009 snprintf(curproxy->check_req, 4, "%c%c%c",
5010 ((unsigned char) packetlen & 0xff),
5011 ((unsigned char) (packetlen >> 8) & 0xff),
5012 ((unsigned char) (packetlen >> 16) & 0xff));
5013
5014 curproxy->check_req[3] = 1;
5015 curproxy->check_req[5] = 130;
5016 curproxy->check_req[11] = 1;
5017 curproxy->check_req[12] = 33;
5018 memcpy(&curproxy->check_req[36], mysqluser, userlen);
5019 curproxy->check_req[36 + userlen + 1 + 1] = 1;
5020 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
5021 cur_arg += 3;
5022 } else {
5023 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
5024 err_code |= ERR_ALERT | ERR_FATAL;
5025 goto out;
5026 }
5027 } else {
5028 packetlen = userlen + 7;
5029 reqlen = packetlen + 9;
5030
5031 free(curproxy->check_req);
5032 curproxy->check_req = (char *)calloc(1, reqlen);
5033 curproxy->check_len = reqlen;
5034
5035 snprintf(curproxy->check_req, 4, "%c%c%c",
5036 ((unsigned char) packetlen & 0xff),
5037 ((unsigned char) (packetlen >> 8) & 0xff),
5038 ((unsigned char) (packetlen >> 16) & 0xff));
5039
5040 curproxy->check_req[3] = 1;
5041 curproxy->check_req[5] = 128;
5042 curproxy->check_req[8] = 1;
5043 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5044 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5045 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5046 cur_arg += 2;
5047 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005048 } else {
5049 /* unknown suboption - catchall */
5050 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5051 file, linenum, args[0], args[1]);
5052 err_code |= ERR_ALERT | ERR_FATAL;
5053 goto out;
5054 }
5055 } /* end while loop */
5056 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005057 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005058 else if (!strcmp(args[1], "ldap-check")) {
5059 /* use LDAP request to check servers' health */
5060 free(curproxy->check_req);
5061 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005062 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005063 curproxy->options2 |= PR_O2_LDAP_CHK;
5064
5065 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
5066 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5067 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005068 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5069 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005070 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005071 else if (!strcmp(args[1], "tcp-check")) {
5072 /* use raw TCPCHK send/expect to check servers' health */
5073 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5074 err_code |= ERR_WARN;
5075
5076 free(curproxy->check_req);
5077 curproxy->check_req = NULL;
5078 curproxy->options2 &= ~PR_O2_CHK_ANY;
5079 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005080 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5081 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005082 }
Simon Horman98637e52014-06-20 12:30:16 +09005083 else if (!strcmp(args[1], "external-check")) {
5084 /* excute an external command to check servers' health */
5085 free(curproxy->check_req);
5086 curproxy->check_req = NULL;
5087 curproxy->options2 &= ~PR_O2_CHK_ANY;
5088 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005089 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5090 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005091 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005092 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005093 int cur_arg;
5094
5095 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5096 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005097 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005098
Willy Tarreau87cf5142011-08-19 22:57:24 +02005099 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005100
5101 free(curproxy->fwdfor_hdr_name);
5102 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5103 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5104
5105 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5106 cur_arg = 2;
5107 while (*(args[cur_arg])) {
5108 if (!strcmp(args[cur_arg], "except")) {
5109 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005110 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005111 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5112 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005113 err_code |= ERR_ALERT | ERR_FATAL;
5114 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005115 }
5116 /* flush useless bits */
5117 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005118 cur_arg += 2;
5119 } else if (!strcmp(args[cur_arg], "header")) {
5120 /* suboption header - needs additional argument for it */
5121 if (*(args[cur_arg+1]) == 0) {
5122 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5123 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005124 err_code |= ERR_ALERT | ERR_FATAL;
5125 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005126 }
5127 free(curproxy->fwdfor_hdr_name);
5128 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5129 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5130 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005131 } else if (!strcmp(args[cur_arg], "if-none")) {
5132 curproxy->options &= ~PR_O_FF_ALWAYS;
5133 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005134 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005135 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005136 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005137 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005138 err_code |= ERR_ALERT | ERR_FATAL;
5139 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005140 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005141 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005142 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005143 else if (!strcmp(args[1], "originalto")) {
5144 int cur_arg;
5145
5146 /* insert x-original-to field, but not for the IP address listed as an except.
5147 * set default options (ie: bitfield, header name, etc)
5148 */
5149
5150 curproxy->options |= PR_O_ORGTO;
5151
5152 free(curproxy->orgto_hdr_name);
5153 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5154 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5155
Willy Tarreau87cf5142011-08-19 22:57:24 +02005156 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005157 cur_arg = 2;
5158 while (*(args[cur_arg])) {
5159 if (!strcmp(args[cur_arg], "except")) {
5160 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005161 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 +02005162 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5163 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005164 err_code |= ERR_ALERT | ERR_FATAL;
5165 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005166 }
5167 /* flush useless bits */
5168 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5169 cur_arg += 2;
5170 } else if (!strcmp(args[cur_arg], "header")) {
5171 /* suboption header - needs additional argument for it */
5172 if (*(args[cur_arg+1]) == 0) {
5173 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5174 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005175 err_code |= ERR_ALERT | ERR_FATAL;
5176 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005177 }
5178 free(curproxy->orgto_hdr_name);
5179 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5180 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5181 cur_arg += 2;
5182 } else {
5183 /* unknown suboption - catchall */
5184 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5185 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005186 err_code |= ERR_ALERT | ERR_FATAL;
5187 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005188 }
5189 } /* end while loop */
5190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005191 else {
5192 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005193 err_code |= ERR_ALERT | ERR_FATAL;
5194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005195 }
Willy Tarreau93893792009-07-23 13:19:11 +02005196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005197 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005198 else if (!strcmp(args[0], "default_backend")) {
5199 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005200 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005201
5202 if (*(args[1]) == 0) {
5203 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005204 err_code |= ERR_ALERT | ERR_FATAL;
5205 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005206 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005207 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005208 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005209
5210 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5211 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005213 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005214 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005215 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005216
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005217 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5218 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 +01005219 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005220 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221 /* enable reconnections to dispatch */
5222 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005223
5224 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5225 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005226 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005227 else if (!strcmp(args[0], "http-reuse")) {
5228 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5229 err_code |= ERR_WARN;
5230
5231 if (strcmp(args[1], "never") == 0) {
5232 /* enable a graceful server shutdown on an HTTP 404 response */
5233 curproxy->options &= ~PR_O_REUSE_MASK;
5234 curproxy->options |= PR_O_REUSE_NEVR;
5235 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5236 goto out;
5237 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005238 else if (strcmp(args[1], "safe") == 0) {
5239 /* enable a graceful server shutdown on an HTTP 404 response */
5240 curproxy->options &= ~PR_O_REUSE_MASK;
5241 curproxy->options |= PR_O_REUSE_SAFE;
5242 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5243 goto out;
5244 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005245 else if (strcmp(args[1], "aggressive") == 0) {
5246 curproxy->options &= ~PR_O_REUSE_MASK;
5247 curproxy->options |= PR_O_REUSE_AGGR;
5248 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5249 goto out;
5250 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005251 else if (strcmp(args[1], "always") == 0) {
5252 /* enable a graceful server shutdown on an HTTP 404 response */
5253 curproxy->options &= ~PR_O_REUSE_MASK;
5254 curproxy->options |= PR_O_REUSE_ALWS;
5255 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5256 goto out;
5257 }
5258 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005259 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005260 err_code |= ERR_ALERT | ERR_FATAL;
5261 goto out;
5262 }
5263 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005264 else if (!strcmp(args[0], "http-check")) {
5265 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005266 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005267
5268 if (strcmp(args[1], "disable-on-404") == 0) {
5269 /* enable a graceful server shutdown on an HTTP 404 response */
5270 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005271 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5272 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005273 }
Willy Tarreauef781042010-01-27 11:53:01 +01005274 else if (strcmp(args[1], "send-state") == 0) {
5275 /* enable emission of the apparent state of a server in HTTP checks */
5276 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005277 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5278 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005279 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005280 else if (strcmp(args[1], "expect") == 0) {
5281 const char *ptr_arg;
5282 int cur_arg;
5283
5284 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5285 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5286 err_code |= ERR_ALERT | ERR_FATAL;
5287 goto out;
5288 }
5289
5290 cur_arg = 2;
5291 /* consider exclamation marks, sole or at the beginning of a word */
5292 while (*(ptr_arg = args[cur_arg])) {
5293 while (*ptr_arg == '!') {
5294 curproxy->options2 ^= PR_O2_EXP_INV;
5295 ptr_arg++;
5296 }
5297 if (*ptr_arg)
5298 break;
5299 cur_arg++;
5300 }
5301 /* now ptr_arg points to the beginning of a word past any possible
5302 * exclamation mark, and cur_arg is the argument which holds this word.
5303 */
5304 if (strcmp(ptr_arg, "status") == 0) {
5305 if (!*(args[cur_arg + 1])) {
5306 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5307 file, linenum, args[0], args[1], ptr_arg);
5308 err_code |= ERR_ALERT | ERR_FATAL;
5309 goto out;
5310 }
5311 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005312 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005313 curproxy->expect_str = strdup(args[cur_arg + 1]);
5314 }
5315 else if (strcmp(ptr_arg, "string") == 0) {
5316 if (!*(args[cur_arg + 1])) {
5317 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5318 file, linenum, args[0], args[1], ptr_arg);
5319 err_code |= ERR_ALERT | ERR_FATAL;
5320 goto out;
5321 }
5322 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005323 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005324 curproxy->expect_str = strdup(args[cur_arg + 1]);
5325 }
5326 else if (strcmp(ptr_arg, "rstatus") == 0) {
5327 if (!*(args[cur_arg + 1])) {
5328 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5329 file, linenum, args[0], args[1], ptr_arg);
5330 err_code |= ERR_ALERT | ERR_FATAL;
5331 goto out;
5332 }
5333 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005334 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005335 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005336 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005337 free(curproxy->expect_regex);
5338 curproxy->expect_regex = NULL;
5339 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005340 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005341 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5342 error = NULL;
5343 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5344 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5345 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5346 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005347 err_code |= ERR_ALERT | ERR_FATAL;
5348 goto out;
5349 }
5350 }
5351 else if (strcmp(ptr_arg, "rstring") == 0) {
5352 if (!*(args[cur_arg + 1])) {
5353 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5354 file, linenum, args[0], args[1], ptr_arg);
5355 err_code |= ERR_ALERT | ERR_FATAL;
5356 goto out;
5357 }
5358 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005359 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005360 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005361 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005362 free(curproxy->expect_regex);
5363 curproxy->expect_regex = NULL;
5364 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005365 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005366 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5367 error = NULL;
5368 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5369 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5370 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5371 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005372 err_code |= ERR_ALERT | ERR_FATAL;
5373 goto out;
5374 }
5375 }
5376 else {
5377 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5378 file, linenum, args[0], args[1], ptr_arg);
5379 err_code |= ERR_ALERT | ERR_FATAL;
5380 goto out;
5381 }
5382 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005383 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005384 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 +02005385 err_code |= ERR_ALERT | ERR_FATAL;
5386 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005387 }
5388 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005389 else if (!strcmp(args[0], "tcp-check")) {
5390 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5391 err_code |= ERR_WARN;
5392
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005393 if (strcmp(args[1], "comment") == 0) {
5394 int cur_arg;
5395 struct tcpcheck_rule *tcpcheck;
5396
5397 cur_arg = 1;
5398 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5399 tcpcheck->action = TCPCHK_ACT_COMMENT;
5400
5401 if (!*args[cur_arg + 1]) {
5402 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5403 file, linenum, args[cur_arg]);
5404 err_code |= ERR_ALERT | ERR_FATAL;
5405 goto out;
5406 }
5407
5408 tcpcheck->comment = strdup(args[cur_arg + 1]);
5409
5410 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005411 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5412 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005413 }
5414 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005415 const char *ptr_arg;
5416 int cur_arg;
5417 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005418
5419 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005420 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5421 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5422 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5423 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5424 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005425
Willy Tarreau5581c272015-05-13 12:24:53 +02005426 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5427 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5428 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5429 file, linenum);
5430 err_code |= ERR_ALERT | ERR_FATAL;
5431 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005432 }
5433
5434 cur_arg = 2;
5435 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5436 tcpcheck->action = TCPCHK_ACT_CONNECT;
5437
5438 /* parsing each parameters to fill up the rule */
5439 while (*(ptr_arg = args[cur_arg])) {
5440 /* tcp port */
5441 if (strcmp(args[cur_arg], "port") == 0) {
5442 if ( (atol(args[cur_arg + 1]) > 65535) ||
5443 (atol(args[cur_arg + 1]) < 1) ){
5444 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5445 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5446 err_code |= ERR_ALERT | ERR_FATAL;
5447 goto out;
5448 }
5449 tcpcheck->port = atol(args[cur_arg + 1]);
5450 cur_arg += 2;
5451 }
5452 /* send proxy protocol */
5453 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5454 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5455 cur_arg++;
5456 }
5457#ifdef USE_OPENSSL
5458 else if (strcmp(args[cur_arg], "ssl") == 0) {
5459 curproxy->options |= PR_O_TCPCHK_SSL;
5460 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5461 cur_arg++;
5462 }
5463#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005464 /* comment for this tcpcheck line */
5465 else if (strcmp(args[cur_arg], "comment") == 0) {
5466 if (!*args[cur_arg + 1]) {
5467 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5468 file, linenum, args[cur_arg]);
5469 err_code |= ERR_ALERT | ERR_FATAL;
5470 goto out;
5471 }
5472 tcpcheck->comment = strdup(args[cur_arg + 1]);
5473 cur_arg += 2;
5474 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005475 else {
5476#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005477 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 +01005478#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005479 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 +01005480#endif /* USE_OPENSSL */
5481 file, linenum, args[0], args[1], args[cur_arg]);
5482 err_code |= ERR_ALERT | ERR_FATAL;
5483 goto out;
5484 }
5485
5486 }
5487
5488 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5489 }
5490 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005491 if (! *(args[2]) ) {
5492 /* SEND string expected */
5493 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5494 file, linenum, args[0], args[1], args[2]);
5495 err_code |= ERR_ALERT | ERR_FATAL;
5496 goto out;
5497 } else {
5498 struct tcpcheck_rule *tcpcheck;
5499
5500 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5501
5502 tcpcheck->action = TCPCHK_ACT_SEND;
5503 tcpcheck->string_len = strlen(args[2]);
5504 tcpcheck->string = strdup(args[2]);
5505 tcpcheck->expect_regex = NULL;
5506
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005507 /* comment for this tcpcheck line */
5508 if (strcmp(args[3], "comment") == 0) {
5509 if (!*args[4]) {
5510 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5511 file, linenum, args[3]);
5512 err_code |= ERR_ALERT | ERR_FATAL;
5513 goto out;
5514 }
5515 tcpcheck->comment = strdup(args[4]);
5516 }
5517
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005518 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5519 }
5520 }
5521 else if (strcmp(args[1], "send-binary") == 0) {
5522 if (! *(args[2]) ) {
5523 /* SEND binary string expected */
5524 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5525 file, linenum, args[0], args[1], args[2]);
5526 err_code |= ERR_ALERT | ERR_FATAL;
5527 goto out;
5528 } else {
5529 struct tcpcheck_rule *tcpcheck;
5530 char *err = NULL;
5531
5532 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5533
5534 tcpcheck->action = TCPCHK_ACT_SEND;
5535 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5536 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5537 file, linenum, args[0], args[1], args[2], err);
5538 err_code |= ERR_ALERT | ERR_FATAL;
5539 goto out;
5540 }
5541 tcpcheck->expect_regex = NULL;
5542
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005543 /* comment for this tcpcheck line */
5544 if (strcmp(args[3], "comment") == 0) {
5545 if (!*args[4]) {
5546 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5547 file, linenum, args[3]);
5548 err_code |= ERR_ALERT | ERR_FATAL;
5549 goto out;
5550 }
5551 tcpcheck->comment = strdup(args[4]);
5552 }
5553
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005554 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5555 }
5556 }
5557 else if (strcmp(args[1], "expect") == 0) {
5558 const char *ptr_arg;
5559 int cur_arg;
5560 int inverse = 0;
5561
5562 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5563 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5564 err_code |= ERR_ALERT | ERR_FATAL;
5565 goto out;
5566 }
5567
5568 cur_arg = 2;
5569 /* consider exclamation marks, sole or at the beginning of a word */
5570 while (*(ptr_arg = args[cur_arg])) {
5571 while (*ptr_arg == '!') {
5572 inverse = !inverse;
5573 ptr_arg++;
5574 }
5575 if (*ptr_arg)
5576 break;
5577 cur_arg++;
5578 }
5579 /* now ptr_arg points to the beginning of a word past any possible
5580 * exclamation mark, and cur_arg is the argument which holds this word.
5581 */
5582 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005583 struct tcpcheck_rule *tcpcheck;
5584 char *err = NULL;
5585
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005586 if (!*(args[cur_arg + 1])) {
5587 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5588 file, linenum, args[0], args[1], ptr_arg);
5589 err_code |= ERR_ALERT | ERR_FATAL;
5590 goto out;
5591 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005592
5593 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5594
5595 tcpcheck->action = TCPCHK_ACT_EXPECT;
5596 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5597 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5598 file, linenum, args[0], args[1], args[2], err);
5599 err_code |= ERR_ALERT | ERR_FATAL;
5600 goto out;
5601 }
5602 tcpcheck->expect_regex = NULL;
5603 tcpcheck->inverse = inverse;
5604
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005605 /* tcpcheck comment */
5606 cur_arg += 2;
5607 if (strcmp(args[cur_arg], "comment") == 0) {
5608 if (!*args[cur_arg + 1]) {
5609 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5610 file, linenum, args[cur_arg + 1]);
5611 err_code |= ERR_ALERT | ERR_FATAL;
5612 goto out;
5613 }
5614 tcpcheck->comment = strdup(args[cur_arg + 1]);
5615 }
5616
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005617 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5618 }
5619 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005620 struct tcpcheck_rule *tcpcheck;
5621
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005622 if (!*(args[cur_arg + 1])) {
5623 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5624 file, linenum, args[0], args[1], ptr_arg);
5625 err_code |= ERR_ALERT | ERR_FATAL;
5626 goto out;
5627 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005628
5629 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5630
5631 tcpcheck->action = TCPCHK_ACT_EXPECT;
5632 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5633 tcpcheck->string = strdup(args[cur_arg + 1]);
5634 tcpcheck->expect_regex = NULL;
5635 tcpcheck->inverse = inverse;
5636
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005637 /* tcpcheck comment */
5638 cur_arg += 2;
5639 if (strcmp(args[cur_arg], "comment") == 0) {
5640 if (!*args[cur_arg + 1]) {
5641 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5642 file, linenum, args[cur_arg + 1]);
5643 err_code |= ERR_ALERT | ERR_FATAL;
5644 goto out;
5645 }
5646 tcpcheck->comment = strdup(args[cur_arg + 1]);
5647 }
5648
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005649 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5650 }
5651 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005652 struct tcpcheck_rule *tcpcheck;
5653
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005654 if (!*(args[cur_arg + 1])) {
5655 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5656 file, linenum, args[0], args[1], ptr_arg);
5657 err_code |= ERR_ALERT | ERR_FATAL;
5658 goto out;
5659 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005660
5661 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5662
5663 tcpcheck->action = TCPCHK_ACT_EXPECT;
5664 tcpcheck->string_len = 0;
5665 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005666 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5667 error = NULL;
5668 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5669 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5670 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5671 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005672 err_code |= ERR_ALERT | ERR_FATAL;
5673 goto out;
5674 }
5675 tcpcheck->inverse = inverse;
5676
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005677 /* tcpcheck comment */
5678 cur_arg += 2;
5679 if (strcmp(args[cur_arg], "comment") == 0) {
5680 if (!*args[cur_arg + 1]) {
5681 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5682 file, linenum, args[cur_arg + 1]);
5683 err_code |= ERR_ALERT | ERR_FATAL;
5684 goto out;
5685 }
5686 tcpcheck->comment = strdup(args[cur_arg + 1]);
5687 }
5688
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005689 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5690 }
5691 else {
5692 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5693 file, linenum, args[0], args[1], ptr_arg);
5694 err_code |= ERR_ALERT | ERR_FATAL;
5695 goto out;
5696 }
5697 }
5698 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005699 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005700 err_code |= ERR_ALERT | ERR_FATAL;
5701 goto out;
5702 }
5703 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005704 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005705 if (curproxy == &defproxy) {
5706 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005707 err_code |= ERR_ALERT | ERR_FATAL;
5708 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005709 }
5710
Willy Tarreaub80c2302007-11-30 20:51:32 +01005711 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005712 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005713
5714 if (strcmp(args[1], "fail") == 0) {
5715 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005716 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005717 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5718 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005719 err_code |= ERR_ALERT | ERR_FATAL;
5720 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005721 }
5722
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005723 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5724 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5725 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005726 err_code |= ERR_ALERT | ERR_FATAL;
5727 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005728 }
5729 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5730 }
5731 else {
5732 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005733 err_code |= ERR_ALERT | ERR_FATAL;
5734 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005735 }
5736 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005737#ifdef TPROXY
5738 else if (!strcmp(args[0], "transparent")) {
5739 /* enable transparent proxy connections */
5740 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005741 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005743 }
5744#endif
5745 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005746 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005747 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005748
Willy Tarreaubaaee002006-06-26 02:48:02 +02005749 if (*(args[1]) == 0) {
5750 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005751 err_code |= ERR_ALERT | ERR_FATAL;
5752 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005753 }
5754 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005755 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005757 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005758 else if (!strcmp(args[0], "backlog")) { /* backlog */
5759 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005760 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005761
5762 if (*(args[1]) == 0) {
5763 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005764 err_code |= ERR_ALERT | ERR_FATAL;
5765 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005766 }
5767 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005768 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5769 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005770 }
Willy Tarreau86034312006-12-29 00:10:33 +01005771 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005772 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005773 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005774
Willy Tarreau86034312006-12-29 00:10:33 +01005775 if (*(args[1]) == 0) {
5776 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005777 err_code |= ERR_ALERT | ERR_FATAL;
5778 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005779 }
5780 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005781 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5782 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005783 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005784 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5785 if (*(args[1]) == 0) {
5786 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005787 err_code |= ERR_ALERT | ERR_FATAL;
5788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005789 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005790 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5791 if (err) {
5792 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5793 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005794 err_code |= ERR_ALERT | ERR_FATAL;
5795 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005796 }
5797 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005798 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5799 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005800 }
5801 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005802 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005803 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005804 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005805
Willy Tarreaubaaee002006-06-26 02:48:02 +02005806 if (curproxy == &defproxy) {
5807 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005808 err_code |= ERR_ALERT | ERR_FATAL;
5809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005810 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005811 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005812 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005813
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005814 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005815 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005816 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005817 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005818 goto out;
5819 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005820
5821 proto = protocol_by_family(sk->ss_family);
5822 if (!proto || !proto->connect) {
5823 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5824 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005825 err_code |= ERR_ALERT | ERR_FATAL;
5826 goto out;
5827 }
5828
5829 if (port1 != port2) {
5830 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5831 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005832 err_code |= ERR_ALERT | ERR_FATAL;
5833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005834 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005835
5836 if (!port1) {
5837 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5838 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005839 err_code |= ERR_ALERT | ERR_FATAL;
5840 goto out;
5841 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005842
William Lallemanddf1425a2015-04-28 20:17:49 +02005843 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5844 goto out;
5845
Willy Tarreaud5191e72010-02-09 20:50:45 +01005846 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005847 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005848 }
5849 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005850 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005851 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005852
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005853 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5854 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005855 err_code |= ERR_ALERT | ERR_FATAL;
5856 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005857 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005858 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005859 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005860 /**
5861 * The syntax for hash-type config element is
5862 * hash-type {map-based|consistent} [[<algo>] avalanche]
5863 *
5864 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5865 */
5866 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005867
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005868 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5869 err_code |= ERR_WARN;
5870
5871 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005872 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5873 }
5874 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005875 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5876 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005877 else if (strcmp(args[1], "avalanche") == 0) {
5878 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]);
5879 err_code |= ERR_ALERT | ERR_FATAL;
5880 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005881 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005882 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005883 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005884 err_code |= ERR_ALERT | ERR_FATAL;
5885 goto out;
5886 }
Bhaskar98634f02013-10-29 23:30:51 -04005887
5888 /* set the hash function to use */
5889 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005890 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005891 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005892
5893 /* if consistent with no argument, then avalanche modifier is also applied */
5894 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5895 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005896 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005897 /* set the hash function */
5898 if (!strcmp(args[2], "sdbm")) {
5899 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5900 }
5901 else if (!strcmp(args[2], "djb2")) {
5902 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005903 }
5904 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005905 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005906 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005907 else if (!strcmp(args[2], "crc32")) {
5908 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5909 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005910 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005911 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 -05005912 err_code |= ERR_ALERT | ERR_FATAL;
5913 goto out;
5914 }
5915
5916 /* set the hash modifier */
5917 if (!strcmp(args[3], "avalanche")) {
5918 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5919 }
5920 else if (*args[3]) {
5921 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5922 err_code |= ERR_ALERT | ERR_FATAL;
5923 goto out;
5924 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005925 }
William Lallemanda73203e2012-03-12 12:48:57 +01005926 }
William Lallemanda73203e2012-03-12 12:48:57 +01005927 else if (strcmp(args[0], "unique-id-format") == 0) {
5928 if (!*(args[1])) {
5929 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5930 err_code |= ERR_ALERT | ERR_FATAL;
5931 goto out;
5932 }
William Lallemand3203ff42012-11-11 17:30:56 +01005933 if (*(args[2])) {
5934 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5935 err_code |= ERR_ALERT | ERR_FATAL;
5936 goto out;
5937 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005938 free(curproxy->conf.uniqueid_format_string);
5939 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005940
Willy Tarreau62a61232013-04-12 18:13:46 +02005941 free(curproxy->conf.uif_file);
5942 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5943 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005944 }
William Lallemanda73203e2012-03-12 12:48:57 +01005945
5946 else if (strcmp(args[0], "unique-id-header") == 0) {
5947 if (!*(args[1])) {
5948 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5949 err_code |= ERR_ALERT | ERR_FATAL;
5950 goto out;
5951 }
5952 free(curproxy->header_unique_id);
5953 curproxy->header_unique_id = strdup(args[1]);
5954 }
5955
William Lallemand723b73a2012-02-08 16:37:49 +01005956 else if (strcmp(args[0], "log-format") == 0) {
5957 if (!*(args[1])) {
5958 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5959 err_code |= ERR_ALERT | ERR_FATAL;
5960 goto out;
5961 }
William Lallemand3203ff42012-11-11 17:30:56 +01005962 if (*(args[2])) {
5963 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5964 err_code |= ERR_ALERT | ERR_FATAL;
5965 goto out;
5966 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005967
Willy Tarreau62a61232013-04-12 18:13:46 +02005968 if (curproxy->conf.logformat_string != default_http_log_format &&
5969 curproxy->conf.logformat_string != default_tcp_log_format &&
5970 curproxy->conf.logformat_string != clf_http_log_format)
5971 free(curproxy->conf.logformat_string);
5972 curproxy->conf.logformat_string = strdup(args[1]);
5973
5974 free(curproxy->conf.lfs_file);
5975 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5976 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005977
5978 /* get a chance to improve log-format error reporting by
5979 * reporting the correct line-number when possible.
5980 */
5981 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5982 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5983 file, linenum, curproxy->id);
5984 err_code |= ERR_WARN;
5985 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005986 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005987 else if (!strcmp(args[0], "log-format-sd")) {
5988 if (!*(args[1])) {
5989 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5990 err_code |= ERR_ALERT | ERR_FATAL;
5991 goto out;
5992 }
5993 if (*(args[2])) {
5994 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5995 err_code |= ERR_ALERT | ERR_FATAL;
5996 goto out;
5997 }
5998
5999 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6000 free(curproxy->conf.logformat_sd_string);
6001 curproxy->conf.logformat_sd_string = strdup(args[1]);
6002
6003 free(curproxy->conf.lfsd_file);
6004 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6005 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6006
6007 /* get a chance to improve log-format-sd error reporting by
6008 * reporting the correct line-number when possible.
6009 */
6010 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6011 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6012 file, linenum, curproxy->id);
6013 err_code |= ERR_WARN;
6014 }
6015 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006016 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6017 if (*(args[1]) == 0) {
6018 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6019 err_code |= ERR_ALERT | ERR_FATAL;
6020 goto out;
6021 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006022 chunk_destroy(&curproxy->log_tag);
6023 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006024 }
William Lallemand0f99e342011-10-12 17:50:54 +02006025 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6026 /* delete previous herited or defined syslog servers */
6027 struct logsrv *back;
6028
6029 if (*(args[1]) != 0) {
6030 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6031 err_code |= ERR_ALERT | ERR_FATAL;
6032 goto out;
6033 }
6034
William Lallemand723b73a2012-02-08 16:37:49 +01006035 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6036 LIST_DEL(&tmplogsrv->list);
6037 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006038 }
6039 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006040 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006041 struct logsrv *logsrv;
6042
Willy Tarreaubaaee002006-06-26 02:48:02 +02006043 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006044 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006045 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02006046 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01006047 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006048 LIST_INIT(&node->list);
6049 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006051 }
6052 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006053 struct sockaddr_storage *sk;
6054 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006055 int arg = 0;
6056 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006057
6058 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006059
Willy Tarreau18324f52014-06-27 18:10:07 +02006060 /* just after the address, a length may be specified */
6061 if (strcmp(args[arg+2], "len") == 0) {
6062 len = atoi(args[arg+3]);
6063 if (len < 80 || len > 65535) {
6064 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6065 file, linenum, args[arg+3]);
6066 err_code |= ERR_ALERT | ERR_FATAL;
6067 goto out;
6068 }
6069 logsrv->maxlen = len;
6070
6071 /* skip these two args */
6072 arg += 2;
6073 }
6074 else
6075 logsrv->maxlen = MAX_SYSLOG_LEN;
6076
6077 if (logsrv->maxlen > global.max_syslog_len) {
6078 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02006079 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02006080 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006081 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006082 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006083 }
6084
Dragan Dosen1322d092015-09-22 16:05:32 +02006085 /* after the length, a format may be specified */
6086 if (strcmp(args[arg+2], "format") == 0) {
6087 logsrv->format = get_log_format(args[arg+3]);
6088 if (logsrv->format < 0) {
6089 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6090 err_code |= ERR_ALERT | ERR_FATAL;
6091 goto out;
6092 }
6093
6094 /* skip these two args */
6095 arg += 2;
6096 }
6097
William Lallemanddf1425a2015-04-28 20:17:49 +02006098 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6099 goto out;
6100
Willy Tarreau18324f52014-06-27 18:10:07 +02006101 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006102 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006103 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006104 err_code |= ERR_ALERT | ERR_FATAL;
6105 goto out;
6106
Willy Tarreaubaaee002006-06-26 02:48:02 +02006107 }
6108
William Lallemand0f99e342011-10-12 17:50:54 +02006109 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006110 if (*(args[arg+3])) {
6111 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006112 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006113 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006114 err_code |= ERR_ALERT | ERR_FATAL;
6115 goto out;
6116
Willy Tarreaubaaee002006-06-26 02:48:02 +02006117 }
6118 }
6119
William Lallemand0f99e342011-10-12 17:50:54 +02006120 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006121 if (*(args[arg+4])) {
6122 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006123 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006124 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006125 err_code |= ERR_ALERT | ERR_FATAL;
6126 goto out;
6127
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006128 }
6129 }
6130
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006131 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006132 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006133 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006134 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006135 goto out;
6136 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006137
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006138 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006139
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006140 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006141 if (port1 != port2) {
6142 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6143 file, linenum, args[0], args[1]);
6144 err_code |= ERR_ALERT | ERR_FATAL;
6145 goto out;
6146 }
6147
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006148 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006149 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006150 }
William Lallemand0f99e342011-10-12 17:50:54 +02006151
6152 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006153 }
6154 else {
6155 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6156 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006157 err_code |= ERR_ALERT | ERR_FATAL;
6158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006159 }
6160 }
6161 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006162 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006163 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006164 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006165 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006166
Willy Tarreau977b8e42006-12-29 14:19:17 +01006167 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006168 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006169
Willy Tarreaubaaee002006-06-26 02:48:02 +02006170 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006171 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6172 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006173 err_code |= ERR_ALERT | ERR_FATAL;
6174 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006175 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006176
6177 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006178 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6179 free(curproxy->conn_src.iface_name);
6180 curproxy->conn_src.iface_name = NULL;
6181 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006182
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006183 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006184 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006185 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006186 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006187 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006188 goto out;
6189 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006190
6191 proto = protocol_by_family(sk->ss_family);
6192 if (!proto || !proto->connect) {
6193 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006194 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006195 err_code |= ERR_ALERT | ERR_FATAL;
6196 goto out;
6197 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006198
6199 if (port1 != port2) {
6200 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6201 file, linenum, args[0], args[1]);
6202 err_code |= ERR_ALERT | ERR_FATAL;
6203 goto out;
6204 }
6205
Willy Tarreauef9a3602012-12-08 22:29:20 +01006206 curproxy->conn_src.source_addr = *sk;
6207 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006208
6209 cur_arg = 2;
6210 while (*(args[cur_arg])) {
6211 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006212#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006213 if (!*args[cur_arg + 1]) {
6214 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6215 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006216 err_code |= ERR_ALERT | ERR_FATAL;
6217 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006218 }
6219
6220 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006221 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6222 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006223 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006224 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6225 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006226 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6227 char *name, *end;
6228
6229 name = args[cur_arg+1] + 7;
6230 while (isspace(*name))
6231 name++;
6232
6233 end = name;
6234 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6235 end++;
6236
Willy Tarreauef9a3602012-12-08 22:29:20 +01006237 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6238 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6239 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6240 curproxy->conn_src.bind_hdr_len = end - name;
6241 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6242 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6243 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006244
6245 /* now look for an occurrence number */
6246 while (isspace(*end))
6247 end++;
6248 if (*end == ',') {
6249 end++;
6250 name = end;
6251 if (*end == '-')
6252 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006253 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006254 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006255 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006256 }
6257
Willy Tarreauef9a3602012-12-08 22:29:20 +01006258 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006259 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6260 " occurrences values smaller than %d.\n",
6261 file, linenum, MAX_HDR_HISTORY);
6262 err_code |= ERR_ALERT | ERR_FATAL;
6263 goto out;
6264 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006265 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006266 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006267
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006268 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006269 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006270 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006271 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006272 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006273 goto out;
6274 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006275
6276 proto = protocol_by_family(sk->ss_family);
6277 if (!proto || !proto->connect) {
6278 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6279 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006280 err_code |= ERR_ALERT | ERR_FATAL;
6281 goto out;
6282 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006283
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006284 if (port1 != port2) {
6285 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6286 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006287 err_code |= ERR_ALERT | ERR_FATAL;
6288 goto out;
6289 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006290 curproxy->conn_src.tproxy_addr = *sk;
6291 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006292 }
6293 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006294#else /* no TPROXY support */
6295 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006296 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006297 err_code |= ERR_ALERT | ERR_FATAL;
6298 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006299#endif
6300 cur_arg += 2;
6301 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006302 }
6303
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006304 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6305#ifdef SO_BINDTODEVICE
6306 if (!*args[cur_arg + 1]) {
6307 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6308 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006309 err_code |= ERR_ALERT | ERR_FATAL;
6310 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006311 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006312 free(curproxy->conn_src.iface_name);
6313 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6314 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006315 global.last_checks |= LSTCHK_NETADM;
6316#else
6317 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6318 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006319 err_code |= ERR_ALERT | ERR_FATAL;
6320 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006321#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006322 cur_arg += 2;
6323 continue;
6324 }
6325 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006326 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006327 err_code |= ERR_ALERT | ERR_FATAL;
6328 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006329 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006330 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006331 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6332 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6333 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006334 err_code |= ERR_ALERT | ERR_FATAL;
6335 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006336 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006337 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006338 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006339 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6340 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006341 err_code |= ERR_ALERT | ERR_FATAL;
6342 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006343 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006344
6345 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006346 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006347 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006348 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006350 }
6351 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006352 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006353 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006354 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006355 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006357 }
6358 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006359 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006360 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006361 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006362 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006364 }
6365 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006366 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006367 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006368 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006369 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006371 }
6372 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006373 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006374 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006375 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006376 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006378 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006379 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006380 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006381 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006382 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006383 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006384 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006385 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006386 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006387 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006388 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6389 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006390 err_code |= ERR_ALERT | ERR_FATAL;
6391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006392 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006393
6394 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006395 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006396 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006397 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006399 }
6400 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006401 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006402 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006403 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006404 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006406 }
6407 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006408 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006409 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006410 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006411 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006412 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006413 }
6414 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006415 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006416 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006417 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006418 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006420 }
6421 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006422 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006423 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006424 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006425 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006427 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006428 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006429 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006430 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006431 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006432 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006433 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006434 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006435 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006436 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006437
Willy Tarreaubaaee002006-06-26 02:48:02 +02006438 if (curproxy == &defproxy) {
6439 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006440 err_code |= ERR_ALERT | ERR_FATAL;
6441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006442 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006443 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006444 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006445
Willy Tarreaubaaee002006-06-26 02:48:02 +02006446 if (*(args[1]) == 0) {
6447 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006448 err_code |= ERR_ALERT | ERR_FATAL;
6449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006450 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006451
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006452 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006453 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6454 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6455 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006456 err_code |= ERR_ALERT | ERR_FATAL;
6457 goto out;
6458 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006459 err_code |= warnif_cond_conflicts(cond,
6460 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6461 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006462 }
6463 else if (*args[2]) {
6464 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6465 file, linenum, args[0], args[2]);
6466 err_code |= ERR_ALERT | ERR_FATAL;
6467 goto out;
6468 }
6469
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006470 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006471 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006472 wl->s = strdup(args[1]);
6473 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006474 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006475 }
6476 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006477 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006478 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6479 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006480 err_code |= ERR_ALERT | ERR_FATAL;
6481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006482 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006483
Willy Tarreauade5ec42010-01-28 19:33:49 +01006484 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006485 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006486 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006487 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006489 }
6490 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006491 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006492 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006493 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006494 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006496 }
6497 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006498 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006499 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006500 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006501 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006503 }
6504 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006505 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006506 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6507 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006508 err_code |= ERR_ALERT | ERR_FATAL;
6509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006510 }
6511
Willy Tarreauade5ec42010-01-28 19:33:49 +01006512 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006513 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006514 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006515 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006516 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006517 }
6518 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006519 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006520 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006521 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006522 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006523 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006524 }
6525 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006526 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006527 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006528 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006529 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006530 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006531 }
6532 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006533 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006534
Willy Tarreaubaaee002006-06-26 02:48:02 +02006535 if (curproxy == &defproxy) {
6536 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006537 err_code |= ERR_ALERT | ERR_FATAL;
6538 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006539 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006540 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006541 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006542
Willy Tarreaubaaee002006-06-26 02:48:02 +02006543 if (*(args[1]) == 0) {
6544 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006545 err_code |= ERR_ALERT | ERR_FATAL;
6546 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006547 }
6548
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006549 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006550 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6551 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6552 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006553 err_code |= ERR_ALERT | ERR_FATAL;
6554 goto out;
6555 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006556 err_code |= warnif_cond_conflicts(cond,
6557 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6558 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006559 }
6560 else if (*args[2]) {
6561 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6562 file, linenum, args[0], args[2]);
6563 err_code |= ERR_ALERT | ERR_FATAL;
6564 goto out;
6565 }
6566
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006567 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006568 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006569 wl->s = strdup(args[1]);
6570 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006571 }
6572 else if (!strcmp(args[0], "errorloc") ||
6573 !strcmp(args[0], "errorloc302") ||
6574 !strcmp(args[0], "errorloc303")) { /* error location */
6575 int errnum, errlen;
6576 char *err;
6577
Willy Tarreau977b8e42006-12-29 14:19:17 +01006578 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006579 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006580
Willy Tarreaubaaee002006-06-26 02:48:02 +02006581 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006582 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006583 err_code |= ERR_ALERT | ERR_FATAL;
6584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006585 }
6586
6587 errnum = atol(args[1]);
6588 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006589 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6590 err = malloc(errlen);
6591 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006592 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006593 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6594 err = malloc(errlen);
6595 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006596 }
6597
Willy Tarreau0f772532006-12-23 20:51:41 +01006598 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6599 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006600 chunk_destroy(&curproxy->errmsg[rc]);
6601 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006602 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006603 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006604 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006605
6606 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006607 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6608 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006609 free(err);
6610 }
6611 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006612 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6613 int errnum, errlen, fd;
6614 char *err;
6615 struct stat stat;
6616
6617 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006618 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006619
6620 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006621 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006622 err_code |= ERR_ALERT | ERR_FATAL;
6623 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006624 }
6625
6626 fd = open(args[2], O_RDONLY);
6627 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6628 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6629 file, linenum, args[2], args[1]);
6630 if (fd >= 0)
6631 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006632 err_code |= ERR_ALERT | ERR_FATAL;
6633 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006634 }
6635
Willy Tarreau27a674e2009-08-17 07:23:33 +02006636 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006637 errlen = stat.st_size;
6638 } else {
6639 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006640 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006641 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006642 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006643 }
6644
6645 err = malloc(errlen); /* malloc() must succeed during parsing */
6646 errnum = read(fd, err, errlen);
6647 if (errnum != errlen) {
6648 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6649 file, linenum, args[2], args[1]);
6650 close(fd);
6651 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006652 err_code |= ERR_ALERT | ERR_FATAL;
6653 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006654 }
6655 close(fd);
6656
6657 errnum = atol(args[1]);
6658 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6659 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006660 chunk_destroy(&curproxy->errmsg[rc]);
6661 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006662 break;
6663 }
6664 }
6665
6666 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006667 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6668 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006669 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006670 free(err);
6671 }
6672 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006673 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006674 struct cfg_kw_list *kwl;
6675 int index;
6676
6677 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6678 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6679 if (kwl->kw[index].section != CFG_LISTEN)
6680 continue;
6681 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6682 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006683 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006684 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006685 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006686 err_code |= ERR_ALERT | ERR_FATAL;
6687 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006688 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006689 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006690 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006691 err_code |= ERR_WARN;
6692 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006693 }
Willy Tarreau93893792009-07-23 13:19:11 +02006694 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006695 }
6696 }
6697 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006698
Willy Tarreau6daf3432008-01-22 16:44:08 +01006699 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006700 err_code |= ERR_ALERT | ERR_FATAL;
6701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006702 }
Willy Tarreau93893792009-07-23 13:19:11 +02006703 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006704 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006705 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006706}
6707
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006708int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006709cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6710{
6711#ifdef CONFIG_HAP_NS
6712 const char *err;
6713 const char *item = args[0];
6714
6715 if (!strcmp(item, "namespace_list")) {
6716 return 0;
6717 }
6718 else if (!strcmp(item, "namespace")) {
6719 size_t idx = 1;
6720 const char *current;
6721 while (*(current = args[idx++])) {
6722 err = invalid_char(current);
6723 if (err) {
6724 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6725 file, linenum, *err, item, current);
6726 return ERR_ALERT | ERR_FATAL;
6727 }
6728
6729 if (netns_store_lookup(current, strlen(current))) {
6730 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6731 file, linenum, current);
6732 return ERR_ALERT | ERR_FATAL;
6733 }
6734 if (!netns_store_insert(current)) {
6735 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6736 file, linenum, current);
6737 return ERR_ALERT | ERR_FATAL;
6738 }
6739 }
6740 }
6741
6742 return 0;
6743#else
6744 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6745 file, linenum);
6746 return ERR_ALERT | ERR_FATAL;
6747#endif
6748}
6749
6750int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006751cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6752{
6753
6754 int err_code = 0;
6755 const char *err;
6756
6757 if (!strcmp(args[0], "userlist")) { /* new userlist */
6758 struct userlist *newul;
6759
6760 if (!*args[1]) {
6761 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6762 file, linenum, args[0]);
6763 err_code |= ERR_ALERT | ERR_FATAL;
6764 goto out;
6765 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006766 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6767 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006768
6769 err = invalid_char(args[1]);
6770 if (err) {
6771 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6772 file, linenum, *err, args[0], args[1]);
6773 err_code |= ERR_ALERT | ERR_FATAL;
6774 goto out;
6775 }
6776
6777 for (newul = userlist; newul; newul = newul->next)
6778 if (!strcmp(newul->name, args[1])) {
6779 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6780 file, linenum, args[1]);
6781 err_code |= ERR_WARN;
6782 goto out;
6783 }
6784
6785 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6786 if (!newul) {
6787 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6788 err_code |= ERR_ALERT | ERR_ABORT;
6789 goto out;
6790 }
6791
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006792 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006793 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006794 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6795 err_code |= ERR_ALERT | ERR_ABORT;
6796 goto out;
6797 }
6798
6799 newul->next = userlist;
6800 userlist = newul;
6801
6802 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006803 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006804 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006805 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006806
6807 if (!*args[1]) {
6808 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6809 file, linenum, args[0]);
6810 err_code |= ERR_ALERT | ERR_FATAL;
6811 goto out;
6812 }
6813
6814 err = invalid_char(args[1]);
6815 if (err) {
6816 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6817 file, linenum, *err, args[0], args[1]);
6818 err_code |= ERR_ALERT | ERR_FATAL;
6819 goto out;
6820 }
6821
William Lallemand4ac9f542015-05-28 18:03:51 +02006822 if (!userlist)
6823 goto out;
6824
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006825 for (ag = userlist->groups; ag; ag = ag->next)
6826 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006827 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6828 file, linenum, args[1], userlist->name);
6829 err_code |= ERR_ALERT;
6830 goto out;
6831 }
6832
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006833 ag = calloc(1, sizeof(*ag));
6834 if (!ag) {
6835 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6836 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006837 goto out;
6838 }
6839
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006840 ag->name = strdup(args[1]);
6841 if (!ag) {
6842 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6843 err_code |= ERR_ALERT | ERR_ABORT;
6844 goto out;
6845 }
6846
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006847 cur_arg = 2;
6848
6849 while (*args[cur_arg]) {
6850 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006851 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006852 cur_arg += 2;
6853 continue;
6854 } else {
6855 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6856 file, linenum, args[0]);
6857 err_code |= ERR_ALERT | ERR_FATAL;
6858 goto out;
6859 }
6860 }
6861
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006862 ag->next = userlist->groups;
6863 userlist->groups = ag;
6864
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006865 } else if (!strcmp(args[0], "user")) { /* new user */
6866 struct auth_users *newuser;
6867 int cur_arg;
6868
6869 if (!*args[1]) {
6870 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6871 file, linenum, args[0]);
6872 err_code |= ERR_ALERT | ERR_FATAL;
6873 goto out;
6874 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006875 if (!userlist)
6876 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006877
6878 for (newuser = userlist->users; newuser; newuser = newuser->next)
6879 if (!strcmp(newuser->user, args[1])) {
6880 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6881 file, linenum, args[1], userlist->name);
6882 err_code |= ERR_ALERT;
6883 goto out;
6884 }
6885
6886 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6887 if (!newuser) {
6888 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6889 err_code |= ERR_ALERT | ERR_ABORT;
6890 goto out;
6891 }
6892
6893 newuser->user = strdup(args[1]);
6894
6895 newuser->next = userlist->users;
6896 userlist->users = newuser;
6897
6898 cur_arg = 2;
6899
6900 while (*args[cur_arg]) {
6901 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006902#ifdef CONFIG_HAP_CRYPT
6903 if (!crypt("", args[cur_arg + 1])) {
6904 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6905 file, linenum, newuser->user);
6906 err_code |= ERR_ALERT | ERR_FATAL;
6907 goto out;
6908 }
6909#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006910 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6911 file, linenum);
6912 err_code |= ERR_ALERT;
6913#endif
6914 newuser->pass = strdup(args[cur_arg + 1]);
6915 cur_arg += 2;
6916 continue;
6917 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6918 newuser->pass = strdup(args[cur_arg + 1]);
6919 newuser->flags |= AU_O_INSECURE;
6920 cur_arg += 2;
6921 continue;
6922 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006923 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006924 cur_arg += 2;
6925 continue;
6926 } else {
6927 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6928 file, linenum, args[0]);
6929 err_code |= ERR_ALERT | ERR_FATAL;
6930 goto out;
6931 }
6932 }
6933 } else {
6934 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6935 err_code |= ERR_ALERT | ERR_FATAL;
6936 }
6937
6938out:
6939 return err_code;
6940}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006941
6942/*
6943 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006944 * Returns the error code, 0 if OK, or any combination of :
6945 * - ERR_ABORT: must abort ASAP
6946 * - ERR_FATAL: we can continue parsing but not start the service
6947 * - ERR_WARN: a warning has been emitted
6948 * - ERR_ALERT: an alert has been emitted
6949 * Only the two first ones can stop processing, the two others are just
6950 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006951 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006952int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006953{
William Lallemand64e84512015-05-12 14:25:37 +02006954 char *thisline;
6955 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006956 FILE *f;
6957 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006958 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006959 struct cfg_section *cs = NULL;
6960 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006961 int readbytes = 0;
6962
6963 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006964 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006965 return -1;
6966 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006967
6968 /* Register internal sections */
6969 if (!cfg_register_section("listen", cfg_parse_listen) ||
6970 !cfg_register_section("frontend", cfg_parse_listen) ||
6971 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006972 !cfg_register_section("defaults", cfg_parse_listen) ||
6973 !cfg_register_section("global", cfg_parse_global) ||
6974 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006975 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006976 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006977 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6978 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006979 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006980
Willy Tarreaubaaee002006-06-26 02:48:02 +02006981 if ((f=fopen(file,"r")) == NULL)
6982 return -1;
6983
William Lallemandb2f07452015-05-12 14:27:13 +02006984next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006985 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006986 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006987 char *end;
6988 char *args[MAX_LINE_ARGS + 1];
6989 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006990 int dquote = 0; /* double quote */
6991 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006992
Willy Tarreaubaaee002006-06-26 02:48:02 +02006993 linenum++;
6994
6995 end = line + strlen(line);
6996
William Lallemand64e84512015-05-12 14:25:37 +02006997 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006998 /* Check if we reached the limit and the last char is not \n.
6999 * Watch out for the last line without the terminating '\n'!
7000 */
William Lallemand64e84512015-05-12 14:25:37 +02007001 char *newline;
7002 int newlinesize = linesize * 2;
7003
7004 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7005 if (newline == NULL) {
7006 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7007 file, linenum);
7008 err_code |= ERR_ALERT | ERR_FATAL;
7009 continue;
7010 }
7011
7012 readbytes = linesize - 1;
7013 linesize = newlinesize;
7014 thisline = newline;
7015 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007016 }
7017
William Lallemand64e84512015-05-12 14:25:37 +02007018 readbytes = 0;
7019
Willy Tarreaubaaee002006-06-26 02:48:02 +02007020 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007021 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007022 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007023
Willy Tarreaubaaee002006-06-26 02:48:02 +02007024 arg = 0;
7025 args[arg] = line;
7026
7027 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007028 if (*line == '"' && !squote) { /* double quote outside single quotes */
7029 if (dquote)
7030 dquote = 0;
7031 else
7032 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007033 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007034 end--;
7035 }
7036 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7037 if (squote)
7038 squote = 0;
7039 else
7040 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007041 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007042 end--;
7043 }
7044 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007045 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7046 * C equivalent value. Other combinations left unchanged (eg: \1).
7047 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007048 int skip = 0;
7049 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7050 *line = line[1];
7051 skip = 1;
7052 }
7053 else if (line[1] == 'r') {
7054 *line = '\r';
7055 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007056 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007057 else if (line[1] == 'n') {
7058 *line = '\n';
7059 skip = 1;
7060 }
7061 else if (line[1] == 't') {
7062 *line = '\t';
7063 skip = 1;
7064 }
7065 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007066 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007067 unsigned char hex1, hex2;
7068 hex1 = toupper(line[2]) - '0';
7069 hex2 = toupper(line[3]) - '0';
7070 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7071 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7072 *line = (hex1<<4) + hex2;
7073 skip = 3;
7074 }
7075 else {
7076 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007077 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007078 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007079 } else if (line[1] == '"') {
7080 *line = '"';
7081 skip = 1;
7082 } else if (line[1] == '\'') {
7083 *line = '\'';
7084 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007085 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7086 *line = '$';
7087 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007088 }
7089 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007090 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007091 end -= skip;
7092 }
7093 line++;
7094 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007095 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007096 /* end of string, end of loop */
7097 *line = 0;
7098 break;
7099 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007100 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007101 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007102 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007103 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007104 line++;
7105 args[++arg] = line;
7106 }
William Lallemandb2f07452015-05-12 14:27:13 +02007107 else if (dquote && *line == '$') {
7108 /* environment variables are evaluated inside double quotes */
7109 char *var_beg;
7110 char *var_end;
7111 char save_char;
7112 char *value;
7113 int val_len;
7114 int newlinesize;
7115 int braces = 0;
7116
7117 var_beg = line + 1;
7118 var_end = var_beg;
7119
7120 if (*var_beg == '{') {
7121 var_beg++;
7122 var_end++;
7123 braces = 1;
7124 }
7125
7126 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7127 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7128 err_code |= ERR_ALERT | ERR_FATAL;
7129 goto next_line; /* skip current line */
7130 }
7131
7132 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7133 var_end++;
7134
7135 save_char = *var_end;
7136 *var_end = '\0';
7137 value = getenv(var_beg);
7138 *var_end = save_char;
7139 val_len = value ? strlen(value) : 0;
7140
7141 if (braces) {
7142 if (*var_end == '}') {
7143 var_end++;
7144 braces = 0;
7145 } else {
7146 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7147 err_code |= ERR_ALERT | ERR_FATAL;
7148 goto next_line; /* skip current line */
7149 }
7150 }
7151
7152 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7153
7154 /* if not enough space in thisline */
7155 if (newlinesize > linesize) {
7156 char *newline;
7157
7158 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7159 if (newline == NULL) {
7160 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7161 err_code |= ERR_ALERT | ERR_FATAL;
7162 goto next_line; /* slip current line */
7163 }
7164 /* recompute pointers if realloc returns a new pointer */
7165 if (newline != thisline) {
7166 int i;
7167 int diff;
7168
7169 for (i = 0; i <= arg; i++) {
7170 diff = args[i] - thisline;
7171 args[i] = newline + diff;
7172 }
7173
7174 diff = var_end - thisline;
7175 var_end = newline + diff;
7176 diff = end - thisline;
7177 end = newline + diff;
7178 diff = line - thisline;
7179 line = newline + diff;
7180 thisline = newline;
7181 }
7182 linesize = newlinesize;
7183 }
7184
7185 /* insert value inside the line */
7186 memmove(line + val_len, var_end, end - var_end + 1);
7187 memcpy(line, value, val_len);
7188 end += val_len - (var_end - line);
7189 line += val_len;
7190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007191 else {
7192 line++;
7193 }
7194 }
William Lallemandb2f07452015-05-12 14:27:13 +02007195
William Lallemandf9873ba2015-05-05 17:37:14 +02007196 if (dquote) {
7197 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7198 err_code |= ERR_ALERT | ERR_FATAL;
7199 }
7200
7201 if (squote) {
7202 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7203 err_code |= ERR_ALERT | ERR_FATAL;
7204 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007205
7206 /* empty line */
7207 if (!**args)
7208 continue;
7209
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007210 if (*line) {
7211 /* we had to stop due to too many args.
7212 * Let's terminate the string, print the offending part then cut the
7213 * last arg.
7214 */
7215 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7216 line++;
7217 *line = '\0';
7218
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007219 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007220 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007221 err_code |= ERR_ALERT | ERR_FATAL;
7222 args[arg] = line;
7223 }
7224
Willy Tarreau540abe42007-05-02 20:50:16 +02007225 /* zero out remaining args and ensure that at least one entry
7226 * is zeroed out.
7227 */
7228 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007229 args[arg] = line;
7230 }
7231
Willy Tarreau3842f002009-06-14 11:39:52 +02007232 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007233 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007234 char *tmp;
7235
Willy Tarreau3842f002009-06-14 11:39:52 +02007236 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007237 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007238 for (arg=0; *args[arg+1]; arg++)
7239 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007240 *tmp = '\0'; // fix the next arg to \0
7241 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007242 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007243 else if (!strcmp(args[0], "default")) {
7244 kwm = KWM_DEF;
7245 for (arg=0; *args[arg+1]; arg++)
7246 args[arg] = args[arg+1]; // shift args after inversion
7247 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007248
William Lallemand0f99e342011-10-12 17:50:54 +02007249 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7250 strcmp(args[0], "log") != 0) {
7251 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007252 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007253 }
7254
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007255 /* detect section start */
7256 list_for_each_entry(ics, &sections, list) {
7257 if (strcmp(args[0], ics->section_name) == 0) {
7258 cursection = ics->section_name;
7259 cs = ics;
7260 break;
7261 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007262 }
7263
Willy Tarreaubaaee002006-06-26 02:48:02 +02007264 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007265 if (cs)
7266 err_code |= cs->section_parser(file, linenum, args, kwm);
7267 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007268 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007269 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007270 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007271
7272 if (err_code & ERR_ABORT)
7273 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007274 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007275 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007276 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007277 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007278 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007279}
7280
Willy Tarreau64ab6072014-09-16 12:17:36 +02007281/* This function propagates processes from frontend <from> to backend <to> so
7282 * that it is always guaranteed that a backend pointed to by a frontend is
7283 * bound to all of its processes. After that, if the target is a "listen"
7284 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007285 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007286 * checked first to ensure that <to> is already bound to all processes of
7287 * <from>, there is no risk of looping and we ensure to follow the shortest
7288 * path to the destination.
7289 *
7290 * It is possible to set <to> to NULL for the first call so that the function
7291 * takes care of visiting the initial frontend in <from>.
7292 *
7293 * It is important to note that the function relies on the fact that all names
7294 * have already been resolved.
7295 */
7296void propagate_processes(struct proxy *from, struct proxy *to)
7297{
7298 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007299
7300 if (to) {
7301 /* check whether we need to go down */
7302 if (from->bind_proc &&
7303 (from->bind_proc & to->bind_proc) == from->bind_proc)
7304 return;
7305
7306 if (!from->bind_proc && !to->bind_proc)
7307 return;
7308
7309 to->bind_proc = from->bind_proc ?
7310 (to->bind_proc | from->bind_proc) : 0;
7311
7312 /* now propagate down */
7313 from = to;
7314 }
7315
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007316 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007317 return;
7318
Willy Tarreauf6b70012014-12-18 14:00:43 +01007319 if (from->state == PR_STSTOPPED)
7320 return;
7321
Willy Tarreau64ab6072014-09-16 12:17:36 +02007322 /* default_backend */
7323 if (from->defbe.be)
7324 propagate_processes(from, from->defbe.be);
7325
7326 /* use_backend */
7327 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007328 if (rule->dynamic)
7329 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007330 to = rule->be.backend;
7331 propagate_processes(from, to);
7332 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007333}
7334
Willy Tarreaubb925012009-07-23 13:36:36 +02007335/*
7336 * Returns the error code, 0 if OK, or any combination of :
7337 * - ERR_ABORT: must abort ASAP
7338 * - ERR_FATAL: we can continue parsing but not start the service
7339 * - ERR_WARN: a warning has been emitted
7340 * - ERR_ALERT: an alert has been emitted
7341 * Only the two first ones can stop processing, the two others are just
7342 * indicators.
7343 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007344int check_config_validity()
7345{
7346 int cfgerr = 0;
7347 struct proxy *curproxy = NULL;
7348 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007349 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007350 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007351 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007352
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007353 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007354 /*
7355 * Now, check for the integrity of all that we have collected.
7356 */
7357
7358 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007359 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007360
Willy Tarreau193b8c62012-11-22 00:17:38 +01007361 if (!global.tune.max_http_hdr)
7362 global.tune.max_http_hdr = MAX_HTTP_HDR;
7363
7364 if (!global.tune.cookie_len)
7365 global.tune.cookie_len = CAPTURE_LEN;
7366
7367 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7368
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007369 /* Post initialisation of the users and groups lists. */
7370 err_code = userlist_postinit();
7371 if (err_code != ERR_NONE)
7372 goto out;
7373
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007374 /* first, we will invert the proxy list order */
7375 curproxy = NULL;
7376 while (proxy) {
7377 struct proxy *next;
7378
7379 next = proxy->next;
7380 proxy->next = curproxy;
7381 curproxy = proxy;
7382 if (!next)
7383 break;
7384 proxy = next;
7385 }
7386
Willy Tarreau419ead82014-09-16 13:41:21 +02007387 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007388 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007389 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007390 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007391 struct act_rule *trule;
7392 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007393 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007394 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007395 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007396
Willy Tarreau050536d2012-10-04 08:47:34 +02007397 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007398 /* proxy ID not set, use automatic numbering with first
7399 * spare entry starting with next_pxid.
7400 */
7401 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7402 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7403 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007404 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007405 next_pxid++;
7406
Willy Tarreau55ea7572007-06-17 19:56:27 +02007407
Willy Tarreaubaaee002006-06-26 02:48:02 +02007408 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007409 /* ensure we don't keep listeners uselessly bound */
7410 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007411 free((void *)curproxy->table.peers.name);
7412 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007413 continue;
7414 }
7415
Willy Tarreau102df612014-05-07 23:56:38 +02007416 /* Check multi-process mode compatibility for the current proxy */
7417
7418 if (curproxy->bind_proc) {
7419 /* an explicit bind-process was specified, let's check how many
7420 * processes remain.
7421 */
David Carliere6c39412015-07-02 07:00:17 +00007422 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007423
7424 curproxy->bind_proc &= nbits(global.nbproc);
7425 if (!curproxy->bind_proc && nbproc == 1) {
7426 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);
7427 curproxy->bind_proc = 1;
7428 }
7429 else if (!curproxy->bind_proc && nbproc > 1) {
7430 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);
7431 curproxy->bind_proc = 0;
7432 }
7433 }
7434
Willy Tarreau3d209582014-05-09 17:06:11 +02007435 /* check and reduce the bind-proc of each listener */
7436 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7437 unsigned long mask;
7438
7439 if (!bind_conf->bind_proc)
7440 continue;
7441
7442 mask = nbits(global.nbproc);
7443 if (curproxy->bind_proc)
7444 mask &= curproxy->bind_proc;
7445 /* mask cannot be null here thanks to the previous checks */
7446
David Carliere6c39412015-07-02 07:00:17 +00007447 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007448 bind_conf->bind_proc &= mask;
7449
7450 if (!bind_conf->bind_proc && nbproc == 1) {
7451 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",
7452 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7453 bind_conf->bind_proc = mask & ~(mask - 1);
7454 }
7455 else if (!bind_conf->bind_proc && nbproc > 1) {
7456 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",
7457 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7458 bind_conf->bind_proc = 0;
7459 }
7460 }
7461
Willy Tarreauff01a212009-03-15 13:46:16 +01007462 switch (curproxy->mode) {
7463 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007464 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007465 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007466 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7467 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007468 cfgerr++;
7469 }
7470
7471 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007472 Warning("config : servers will be ignored for %s '%s'.\n",
7473 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007474 break;
7475
7476 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007477 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007478 break;
7479
7480 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007481 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007482 break;
7483 }
7484
Willy Tarreauf3934b82015-08-11 11:36:45 +02007485 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7486 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7487 proxy_type_str(curproxy), curproxy->id);
7488 err_code |= ERR_WARN;
7489 }
7490
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007491 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007492 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007493 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007494 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7495 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007496 cfgerr++;
7497 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007498#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007499 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007500 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7501 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007502 cfgerr++;
7503 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007504#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007505 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007506 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7507 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007508 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007509 }
7510 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007511 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007512 /* If no LB algo is set in a backend, and we're not in
7513 * transparent mode, dispatch mode nor proxy mode, we
7514 * want to use balance roundrobin by default.
7515 */
7516 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7517 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007518 }
7519 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007520
Willy Tarreau1620ec32011-08-06 17:05:02 +02007521 if (curproxy->options & PR_O_DISPATCH)
7522 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7523 else if (curproxy->options & PR_O_HTTP_PROXY)
7524 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7525 else if (curproxy->options & PR_O_TRANSP)
7526 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007527
Willy Tarreau1620ec32011-08-06 17:05:02 +02007528 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7529 if (curproxy->options & PR_O_DISABLE404) {
7530 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7531 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7532 err_code |= ERR_WARN;
7533 curproxy->options &= ~PR_O_DISABLE404;
7534 }
7535 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7536 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7537 "send-state", proxy_type_str(curproxy), curproxy->id);
7538 err_code |= ERR_WARN;
7539 curproxy->options &= ~PR_O2_CHK_SNDST;
7540 }
Willy Tarreauef781042010-01-27 11:53:01 +01007541 }
7542
Simon Horman98637e52014-06-20 12:30:16 +09007543 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7544 if (!global.external_check) {
7545 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7546 curproxy->id, "option external-check");
7547 cfgerr++;
7548 }
7549 if (!curproxy->check_command) {
7550 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7551 curproxy->id, "option external-check");
7552 cfgerr++;
7553 }
7554 }
7555
Simon Horman64e34162015-02-06 11:11:57 +09007556 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007557 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7558 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007559 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7560 "'email-alert myhostname', or 'email-alert to' "
7561 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007562 "to be present).\n",
7563 proxy_type_str(curproxy), curproxy->id);
7564 err_code |= ERR_WARN;
7565 free_email_alert(curproxy);
7566 }
7567 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007568 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007569 }
7570
Simon Horman98637e52014-06-20 12:30:16 +09007571 if (curproxy->check_command) {
7572 int clear = 0;
7573 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7574 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7575 "external-check command", proxy_type_str(curproxy), curproxy->id);
7576 err_code |= ERR_WARN;
7577 clear = 1;
7578 }
7579 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007580 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007581 curproxy->id, "external-check command");
7582 cfgerr++;
7583 }
7584 if (clear) {
7585 free(curproxy->check_command);
7586 curproxy->check_command = NULL;
7587 }
7588 }
7589
7590 if (curproxy->check_path) {
7591 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7592 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7593 "external-check path", proxy_type_str(curproxy), curproxy->id);
7594 err_code |= ERR_WARN;
7595 free(curproxy->check_path);
7596 curproxy->check_path = NULL;
7597 }
7598 }
7599
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007600 /* if a default backend was specified, let's find it */
7601 if (curproxy->defbe.name) {
7602 struct proxy *target;
7603
Willy Tarreauafb39922015-05-26 12:04:09 +02007604 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007605 if (!target) {
7606 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7607 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007608 cfgerr++;
7609 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007610 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7611 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007612 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007613 } else if (target->mode != curproxy->mode &&
7614 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7615
7616 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7617 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7618 curproxy->conf.file, curproxy->conf.line,
7619 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7620 target->conf.file, target->conf.line);
7621 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007622 } else {
7623 free(curproxy->defbe.name);
7624 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007625
7626 /* Emit a warning if this proxy also has some servers */
7627 if (curproxy->srv) {
7628 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7629 curproxy->id);
7630 err_code |= ERR_WARN;
7631 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007632 }
7633 }
7634
Willy Tarreau55ea7572007-06-17 19:56:27 +02007635 /* find the target proxy for 'use_backend' rules */
7636 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007637 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007638 struct logformat_node *node;
7639 char *pxname;
7640
7641 /* Try to parse the string as a log format expression. If the result
7642 * of the parsing is only one entry containing a simple string, then
7643 * it's a standard string corresponding to a static rule, thus the
7644 * parsing is cancelled and be.name is restored to be resolved.
7645 */
7646 pxname = rule->be.name;
7647 LIST_INIT(&rule->be.expr);
7648 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7649 curproxy->conf.args.file, curproxy->conf.args.line);
7650 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7651
7652 if (!LIST_ISEMPTY(&rule->be.expr)) {
7653 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7654 rule->dynamic = 1;
7655 free(pxname);
7656 continue;
7657 }
7658 /* simple string: free the expression and fall back to static rule */
7659 free(node->arg);
7660 free(node);
7661 }
7662
7663 rule->dynamic = 0;
7664 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007665
Willy Tarreauafb39922015-05-26 12:04:09 +02007666 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007667 if (!target) {
7668 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7669 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007670 cfgerr++;
7671 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007672 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7673 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007674 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007675 } else if (target->mode != curproxy->mode &&
7676 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7677
7678 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7679 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7680 curproxy->conf.file, curproxy->conf.line,
7681 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7682 target->conf.file, target->conf.line);
7683 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007684 } else {
7685 free((void *)rule->be.name);
7686 rule->be.backend = target;
7687 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007688 }
7689
Willy Tarreau64ab6072014-09-16 12:17:36 +02007690 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007691 list_for_each_entry(srule, &curproxy->server_rules, list) {
7692 struct server *target = findserver(curproxy, srule->srv.name);
7693
7694 if (!target) {
7695 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7696 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7697 cfgerr++;
7698 continue;
7699 }
7700 free((void *)srule->srv.name);
7701 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007702 }
7703
Emeric Brunb982a3d2010-01-04 15:45:53 +01007704 /* find the target table for 'stick' rules */
7705 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7706 struct proxy *target;
7707
Emeric Brun1d33b292010-01-04 15:47:17 +01007708 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7709 if (mrule->flags & STK_IS_STORE)
7710 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7711
Emeric Brunb982a3d2010-01-04 15:45:53 +01007712 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007713 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007714 else
7715 target = curproxy;
7716
7717 if (!target) {
7718 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7719 curproxy->id, mrule->table.name);
7720 cfgerr++;
7721 }
7722 else if (target->table.size == 0) {
7723 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7724 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7725 cfgerr++;
7726 }
Willy Tarreau12785782012-04-27 21:37:17 +02007727 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7728 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007729 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7730 cfgerr++;
7731 }
7732 else {
7733 free((void *)mrule->table.name);
7734 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007735 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007736 }
7737 }
7738
7739 /* find the target table for 'store response' rules */
7740 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7741 struct proxy *target;
7742
Emeric Brun1d33b292010-01-04 15:47:17 +01007743 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7744
Emeric Brunb982a3d2010-01-04 15:45:53 +01007745 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007746 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007747 else
7748 target = curproxy;
7749
7750 if (!target) {
7751 Alert("Proxy '%s': unable to find store table '%s'.\n",
7752 curproxy->id, mrule->table.name);
7753 cfgerr++;
7754 }
7755 else if (target->table.size == 0) {
7756 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7757 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7758 cfgerr++;
7759 }
Willy Tarreau12785782012-04-27 21:37:17 +02007760 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7761 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007762 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7763 cfgerr++;
7764 }
7765 else {
7766 free((void *)mrule->table.name);
7767 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007768 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007769 }
7770 }
7771
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007772 /* find the target table for 'tcp-request' layer 4 rules */
7773 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7774 struct proxy *target;
7775
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007776 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007777 continue;
7778
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007779 if (trule->arg.trk_ctr.table.n)
7780 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007781 else
7782 target = curproxy;
7783
7784 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007785 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007786 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007787 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007788 cfgerr++;
7789 }
7790 else if (target->table.size == 0) {
7791 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007792 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007793 cfgerr++;
7794 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007795 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007796 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007797 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007798 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007799 cfgerr++;
7800 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007801 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007802 free(trule->arg.trk_ctr.table.n);
7803 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007804 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007805 * to pass a list of counters to track and allocate them right here using
7806 * stktable_alloc_data_type().
7807 */
7808 }
7809 }
7810
Willy Tarreaud1f96522010-08-03 19:34:32 +02007811 /* find the target table for 'tcp-request' layer 6 rules */
7812 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7813 struct proxy *target;
7814
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007815 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007816 continue;
7817
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007818 if (trule->arg.trk_ctr.table.n)
7819 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007820 else
7821 target = curproxy;
7822
7823 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007824 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007825 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007826 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007827 cfgerr++;
7828 }
7829 else if (target->table.size == 0) {
7830 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007831 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007832 cfgerr++;
7833 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007834 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007835 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007836 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007837 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007838 cfgerr++;
7839 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007840 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007841 free(trule->arg.trk_ctr.table.n);
7842 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007843 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007844 * to pass a list of counters to track and allocate them right here using
7845 * stktable_alloc_data_type().
7846 */
7847 }
7848 }
7849
Baptiste Assmanne9544932015-11-03 23:31:35 +01007850 /* parse http-request capture rules to ensure id really exists */
7851 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7852 if (hrqrule->action != ACT_CUSTOM ||
7853 hrqrule->action_ptr != http_action_req_capture_by_id)
7854 continue;
7855
7856 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7857 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7858 curproxy->id, hrqrule->arg.capid.idx);
7859 cfgerr++;
7860 }
7861 }
7862
7863 /* parse http-response capture rules to ensure id really exists */
7864 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7865 if (hrqrule->action != ACT_CUSTOM ||
7866 hrqrule->action_ptr != http_action_res_capture_by_id)
7867 continue;
7868
7869 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7870 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7871 curproxy->id, hrqrule->arg.capid.idx);
7872 cfgerr++;
7873 }
7874 }
7875
Willy Tarreau09448f72014-06-25 18:12:15 +02007876 /* find the target table for 'http-request' layer 7 rules */
7877 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7878 struct proxy *target;
7879
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007880 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007881 continue;
7882
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007883 if (hrqrule->arg.trk_ctr.table.n)
7884 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007885 else
7886 target = curproxy;
7887
7888 if (!target) {
7889 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007890 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007891 http_req_trk_idx(hrqrule->action));
7892 cfgerr++;
7893 }
7894 else if (target->table.size == 0) {
7895 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007896 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007897 cfgerr++;
7898 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007899 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007900 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007901 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007902 http_req_trk_idx(hrqrule->action));
7903 cfgerr++;
7904 }
7905 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007906 free(hrqrule->arg.trk_ctr.table.n);
7907 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007908 /* Note: if we decide to enhance the track-sc syntax, we may be able
7909 * to pass a list of counters to track and allocate them right here using
7910 * stktable_alloc_data_type().
7911 */
7912 }
7913 }
7914
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007915 /* move any "block" rules at the beginning of the http-request rules */
7916 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7917 /* insert block_rules into http_req_rules at the beginning */
7918 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7919 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7920 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7921 curproxy->http_req_rules.n = curproxy->block_rules.n;
7922 LIST_INIT(&curproxy->block_rules);
7923 }
7924
Emeric Brun32da3c42010-09-23 18:39:19 +02007925 if (curproxy->table.peers.name) {
7926 struct peers *curpeers = peers;
7927
7928 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7929 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7930 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007931 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007932 break;
7933 }
7934 }
7935
7936 if (!curpeers) {
7937 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7938 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007939 free((void *)curproxy->table.peers.name);
7940 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007941 cfgerr++;
7942 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007943 else if (curpeers->state == PR_STSTOPPED) {
7944 /* silently disable this peers section */
7945 curproxy->table.peers.p = NULL;
7946 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007947 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007948 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7949 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007950 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007951 cfgerr++;
7952 }
7953 }
7954
Simon Horman9dc49962015-01-30 11:22:59 +09007955
7956 if (curproxy->email_alert.mailers.name) {
7957 struct mailers *curmailers = mailers;
7958
7959 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7960 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7961 free(curproxy->email_alert.mailers.name);
7962 curproxy->email_alert.mailers.m = curmailers;
7963 curmailers->users++;
7964 break;
7965 }
7966 }
7967
7968 if (!curmailers) {
7969 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7970 curproxy->id, curproxy->email_alert.mailers.name);
7971 free_email_alert(curproxy);
7972 cfgerr++;
7973 }
7974 }
7975
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007976 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007977 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007978 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7979 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7980 "proxy", curproxy->id);
7981 cfgerr++;
7982 goto out_uri_auth_compat;
7983 }
7984
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007985 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007986 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007987 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007988 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007989
Willy Tarreau95fa4692010-02-01 13:05:50 +01007990 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7991 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007992
7993 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007994 uri_auth_compat_req[i++] = "realm";
7995 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7996 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007997
Willy Tarreau95fa4692010-02-01 13:05:50 +01007998 uri_auth_compat_req[i++] = "unless";
7999 uri_auth_compat_req[i++] = "{";
8000 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8001 uri_auth_compat_req[i++] = "}";
8002 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008003
Willy Tarreauff011f22011-01-06 17:51:27 +01008004 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8005 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008006 cfgerr++;
8007 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008008 }
8009
Willy Tarreauff011f22011-01-06 17:51:27 +01008010 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008011
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008012 if (curproxy->uri_auth->auth_realm) {
8013 free(curproxy->uri_auth->auth_realm);
8014 curproxy->uri_auth->auth_realm = NULL;
8015 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008016
8017 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008018 }
8019out_uri_auth_compat:
8020
Dragan Dosen43885c72015-10-01 13:18:13 +02008021 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008022 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008023 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8024 if (!curproxy->conf.logformat_sd_string) {
8025 /* set the default logformat_sd_string */
8026 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8027 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008028 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008029 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008030 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008031
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008032 /* compile the log format */
8033 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008034 if (curproxy->conf.logformat_string != default_http_log_format &&
8035 curproxy->conf.logformat_string != default_tcp_log_format &&
8036 curproxy->conf.logformat_string != clf_http_log_format)
8037 free(curproxy->conf.logformat_string);
8038 curproxy->conf.logformat_string = NULL;
8039 free(curproxy->conf.lfs_file);
8040 curproxy->conf.lfs_file = NULL;
8041 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008042
8043 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8044 free(curproxy->conf.logformat_sd_string);
8045 curproxy->conf.logformat_sd_string = NULL;
8046 free(curproxy->conf.lfsd_file);
8047 curproxy->conf.lfsd_file = NULL;
8048 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008049 }
8050
Willy Tarreau62a61232013-04-12 18:13:46 +02008051 if (curproxy->conf.logformat_string) {
8052 curproxy->conf.args.ctx = ARGC_LOG;
8053 curproxy->conf.args.file = curproxy->conf.lfs_file;
8054 curproxy->conf.args.line = curproxy->conf.lfs_line;
8055 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008056 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008057 curproxy->conf.args.file = NULL;
8058 curproxy->conf.args.line = 0;
8059 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008060
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008061 if (curproxy->conf.logformat_sd_string) {
8062 curproxy->conf.args.ctx = ARGC_LOGSD;
8063 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8064 curproxy->conf.args.line = curproxy->conf.lfsd_line;
8065 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
8066 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
8067 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
8068 curproxy->conf.args.file = NULL;
8069 curproxy->conf.args.line = 0;
8070 }
8071
Willy Tarreau62a61232013-04-12 18:13:46 +02008072 if (curproxy->conf.uniqueid_format_string) {
8073 curproxy->conf.args.ctx = ARGC_UIF;
8074 curproxy->conf.args.file = curproxy->conf.uif_file;
8075 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01008076 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08008077 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008078 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008079 curproxy->conf.args.file = NULL;
8080 curproxy->conf.args.line = 0;
8081 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008082
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008083 /* only now we can check if some args remain unresolved.
8084 * This must be done after the users and groups resolution.
8085 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008086 cfgerr += smp_resolve_args(curproxy);
8087 if (!cfgerr)
8088 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008089
Willy Tarreau2738a142006-07-08 17:28:09 +02008090 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008091 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008092 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008093 (!curproxy->timeout.connect ||
8094 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008095 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008096 " | While not properly invalid, you will certainly encounter various problems\n"
8097 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008098 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008099 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008100 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008101 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008102
Willy Tarreau1fa31262007-12-03 00:36:16 +01008103 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8104 * We must still support older configurations, so let's find out whether those
8105 * parameters have been set or must be copied from contimeouts.
8106 */
8107 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008108 if (!curproxy->timeout.tarpit ||
8109 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008110 /* tarpit timeout not set. We search in the following order:
8111 * default.tarpit, curr.connect, default.connect.
8112 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008113 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008114 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008115 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008116 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008117 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008118 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008119 }
8120 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008121 (!curproxy->timeout.queue ||
8122 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008123 /* queue timeout not set. We search in the following order:
8124 * default.queue, curr.connect, default.connect.
8125 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008126 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008127 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008128 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008129 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008130 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008131 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008132 }
8133 }
8134
Willy Tarreau1620ec32011-08-06 17:05:02 +02008135 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008136 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
8137 curproxy->check_req = (char *)malloc(curproxy->check_len);
8138 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008139 }
8140
Willy Tarreau215663d2014-06-13 18:30:23 +02008141 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8142 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8143 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8144 proxy_type_str(curproxy), curproxy->id);
8145 err_code |= ERR_WARN;
8146 }
8147
Willy Tarreau193b8c62012-11-22 00:17:38 +01008148 /* ensure that cookie capture length is not too large */
8149 if (curproxy->capture_len >= global.tune.cookie_len) {
8150 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8151 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8152 err_code |= ERR_WARN;
8153 curproxy->capture_len = global.tune.cookie_len - 1;
8154 }
8155
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008156 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008157 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008158 curproxy->req_cap_pool = create_pool("ptrcap",
8159 curproxy->nb_req_cap * sizeof(char *),
8160 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008161 }
8162
8163 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008164 curproxy->rsp_cap_pool = create_pool("ptrcap",
8165 curproxy->nb_rsp_cap * sizeof(char *),
8166 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008167 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008168
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008169 switch (curproxy->load_server_state_from_file) {
8170 case PR_SRV_STATE_FILE_UNSPEC:
8171 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8172 break;
8173 case PR_SRV_STATE_FILE_GLOBAL:
8174 if (!global.server_state_file) {
8175 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",
8176 curproxy->id);
8177 err_code |= ERR_WARN;
8178 }
8179 break;
8180 }
8181
Willy Tarreaubaaee002006-06-26 02:48:02 +02008182 /* first, we will invert the servers list order */
8183 newsrv = NULL;
8184 while (curproxy->srv) {
8185 struct server *next;
8186
8187 next = curproxy->srv->next;
8188 curproxy->srv->next = newsrv;
8189 newsrv = curproxy->srv;
8190 if (!next)
8191 break;
8192 curproxy->srv = next;
8193 }
8194
Willy Tarreau17edc812014-01-03 12:14:34 +01008195 /* Check that no server name conflicts. This causes trouble in the stats.
8196 * We only emit a warning for the first conflict affecting each server,
8197 * in order to avoid combinatory explosion if all servers have the same
8198 * name. We do that only for servers which do not have an explicit ID,
8199 * because these IDs were made also for distinguishing them and we don't
8200 * want to annoy people who correctly manage them.
8201 */
8202 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8203 struct server *other_srv;
8204
8205 if (newsrv->puid)
8206 continue;
8207
8208 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8209 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8210 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8211 newsrv->conf.file, newsrv->conf.line,
8212 proxy_type_str(curproxy), curproxy->id,
8213 newsrv->id, other_srv->conf.line);
8214 break;
8215 }
8216 }
8217 }
8218
Willy Tarreaudd701652010-05-25 23:03:02 +02008219 /* assign automatic UIDs to servers which don't have one yet */
8220 next_id = 1;
8221 newsrv = curproxy->srv;
8222 while (newsrv != NULL) {
8223 if (!newsrv->puid) {
8224 /* server ID not set, use automatic numbering with first
8225 * spare entry starting with next_svid.
8226 */
8227 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8228 newsrv->conf.id.key = newsrv->puid = next_id;
8229 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8230 }
8231 next_id++;
8232 newsrv = newsrv->next;
8233 }
8234
Willy Tarreau20697042007-11-15 23:26:18 +01008235 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008236 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008237
Willy Tarreau62c3be22012-01-20 13:12:32 +01008238 /*
8239 * If this server supports a maxconn parameter, it needs a dedicated
8240 * tasks to fill the emptied slots when a connection leaves.
8241 * Also, resolve deferred tracking dependency if needed.
8242 */
8243 newsrv = curproxy->srv;
8244 while (newsrv != NULL) {
8245 if (newsrv->minconn > newsrv->maxconn) {
8246 /* Only 'minconn' was specified, or it was higher than or equal
8247 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8248 * this will avoid further useless expensive computations.
8249 */
8250 newsrv->maxconn = newsrv->minconn;
8251 } else if (newsrv->maxconn && !newsrv->minconn) {
8252 /* minconn was not specified, so we set it to maxconn */
8253 newsrv->minconn = newsrv->maxconn;
8254 }
8255
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008256#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008257 if (newsrv->use_ssl || newsrv->check.use_ssl)
8258 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008259#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008260
Willy Tarreau2f075e92013-12-03 11:11:34 +01008261 /* set the check type on the server */
8262 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8263
Willy Tarreau62c3be22012-01-20 13:12:32 +01008264 if (newsrv->trackit) {
8265 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008266 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008267 char *pname, *sname;
8268
8269 pname = newsrv->trackit;
8270 sname = strrchr(pname, '/');
8271
8272 if (sname)
8273 *sname++ = '\0';
8274 else {
8275 sname = pname;
8276 pname = NULL;
8277 }
8278
8279 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008280 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008281 if (!px) {
8282 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8283 proxy_type_str(curproxy), curproxy->id,
8284 newsrv->id, pname);
8285 cfgerr++;
8286 goto next_srv;
8287 }
8288 } else
8289 px = curproxy;
8290
8291 srv = findserver(px, sname);
8292 if (!srv) {
8293 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8294 proxy_type_str(curproxy), curproxy->id,
8295 newsrv->id, sname);
8296 cfgerr++;
8297 goto next_srv;
8298 }
8299
Willy Tarreau32091232014-05-16 13:52:00 +02008300 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8301 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8302 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008303 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008304 "tracking as it does not have any check nor agent enabled.\n",
8305 proxy_type_str(curproxy), curproxy->id,
8306 newsrv->id, px->id, srv->id);
8307 cfgerr++;
8308 goto next_srv;
8309 }
8310
8311 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8312
8313 if (loop) {
8314 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8315 "belongs to a tracking chain looping back to %s/%s.\n",
8316 proxy_type_str(curproxy), curproxy->id,
8317 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008318 cfgerr++;
8319 goto next_srv;
8320 }
8321
8322 if (curproxy != px &&
8323 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8324 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8325 "tracking: disable-on-404 option inconsistency.\n",
8326 proxy_type_str(curproxy), curproxy->id,
8327 newsrv->id, px->id, srv->id);
8328 cfgerr++;
8329 goto next_srv;
8330 }
8331
8332 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008333 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008334 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008335 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008336 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008337 }
8338
8339 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008340 newsrv->tracknext = srv->trackers;
8341 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008342
8343 free(newsrv->trackit);
8344 newsrv->trackit = NULL;
8345 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008346
8347 /*
8348 * resolve server's resolvers name and update the resolvers pointer
8349 * accordingly
8350 */
8351 if (newsrv->resolvers_id) {
8352 struct dns_resolvers *curr_resolvers;
8353 int found;
8354
8355 found = 0;
8356 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8357 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8358 found = 1;
8359 break;
8360 }
8361 }
8362
8363 if (!found) {
8364 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8365 proxy_type_str(curproxy), curproxy->id,
8366 newsrv->id, newsrv->resolvers_id);
8367 cfgerr++;
8368 } else {
8369 free(newsrv->resolvers_id);
8370 newsrv->resolvers_id = NULL;
8371 if (newsrv->resolution)
8372 newsrv->resolution->resolvers = curr_resolvers;
8373 }
8374 }
8375 else {
8376 /* if no resolvers section associated to this server
8377 * we can clean up the associated resolution structure
8378 */
8379 if (newsrv->resolution) {
8380 free(newsrv->resolution->hostname_dn);
8381 newsrv->resolution->hostname_dn = NULL;
8382 free(newsrv->resolution);
8383 newsrv->resolution = NULL;
8384 }
8385 }
8386
Willy Tarreau62c3be22012-01-20 13:12:32 +01008387 next_srv:
8388 newsrv = newsrv->next;
8389 }
8390
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008391 /* We have to initialize the server lookup mechanism depending
8392 * on what LB algorithm was choosen.
8393 */
8394
8395 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8396 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8397 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008398 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8399 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8400 init_server_map(curproxy);
8401 } else {
8402 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8403 fwrr_init_server_groups(curproxy);
8404 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008405 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008406
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008407 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008408 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8409 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8410 fwlc_init_server_tree(curproxy);
8411 } else {
8412 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8413 fas_init_server_tree(curproxy);
8414 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008415 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008416
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008417 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008418 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8419 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8420 chash_init_server_tree(curproxy);
8421 } else {
8422 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8423 init_server_map(curproxy);
8424 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008425 break;
8426 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008427
8428 if (curproxy->options & PR_O_LOGASAP)
8429 curproxy->to_log &= ~LW_BYTES;
8430
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008431 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008432 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8433 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008434 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8435 proxy_type_str(curproxy), curproxy->id);
8436 err_code |= ERR_WARN;
8437 }
8438
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008439 if (curproxy->mode != PR_MODE_HTTP) {
8440 int optnum;
8441
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008442 if (curproxy->uri_auth) {
8443 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8444 proxy_type_str(curproxy), curproxy->id);
8445 err_code |= ERR_WARN;
8446 curproxy->uri_auth = NULL;
8447 }
8448
Willy Tarreau87cf5142011-08-19 22:57:24 +02008449 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008450 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8451 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8452 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008453 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008454 }
8455
8456 if (curproxy->options & PR_O_ORGTO) {
8457 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8458 "originalto", proxy_type_str(curproxy), curproxy->id);
8459 err_code |= ERR_WARN;
8460 curproxy->options &= ~PR_O_ORGTO;
8461 }
8462
8463 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8464 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8465 (curproxy->cap & cfg_opts[optnum].cap) &&
8466 (curproxy->options & cfg_opts[optnum].val)) {
8467 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8468 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8469 err_code |= ERR_WARN;
8470 curproxy->options &= ~cfg_opts[optnum].val;
8471 }
8472 }
8473
8474 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8475 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8476 (curproxy->cap & cfg_opts2[optnum].cap) &&
8477 (curproxy->options2 & cfg_opts2[optnum].val)) {
8478 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8479 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8480 err_code |= ERR_WARN;
8481 curproxy->options2 &= ~cfg_opts2[optnum].val;
8482 }
8483 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008484
Willy Tarreau29fbe512015-08-20 19:35:14 +02008485#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008486 if (curproxy->conn_src.bind_hdr_occ) {
8487 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008488 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008489 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008490 err_code |= ERR_WARN;
8491 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008492#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008493 }
8494
Willy Tarreaubaaee002006-06-26 02:48:02 +02008495 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008496 * ensure that we're not cross-dressing a TCP server into HTTP.
8497 */
8498 newsrv = curproxy->srv;
8499 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008500 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008501 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8502 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008503 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008504 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008505
Willy Tarreau0cec3312011-10-31 13:49:26 +01008506 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8507 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8508 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8509 err_code |= ERR_WARN;
8510 }
8511
Willy Tarreauc93cd162014-05-13 15:54:22 +02008512 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008513 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8514 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8515 err_code |= ERR_WARN;
8516 }
8517
Willy Tarreau29fbe512015-08-20 19:35:14 +02008518#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008519 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8520 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008521 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 +01008522 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008523 err_code |= ERR_WARN;
8524 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008525#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008526 newsrv = newsrv->next;
8527 }
8528
Willy Tarreaue42bd962014-09-16 16:21:19 +02008529 /* check if we have a frontend with "tcp-request content" looking at L7
8530 * with no inspect-delay
8531 */
8532 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8533 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008534 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008535 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008536 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008537 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008538 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008539 break;
8540 }
8541
8542 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8543 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8544 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8545 " This means that these rules will randomly find their contents. This can be fixed by"
8546 " setting the tcp-request inspect-delay.\n",
8547 proxy_type_str(curproxy), curproxy->id);
8548 err_code |= ERR_WARN;
8549 }
8550 }
8551
Christopher Fauletd7c91962015-04-30 11:48:27 +02008552 /* Check filter configuration, if any */
8553 cfgerr += flt_check(curproxy);
8554
Willy Tarreauc1a21672009-08-16 22:37:44 +02008555 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008556 if (!curproxy->accept)
8557 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008558
Willy Tarreauc1a21672009-08-16 22:37:44 +02008559 if (curproxy->tcp_req.inspect_delay ||
8560 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008561 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008562
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008563 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008564 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008565 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008566 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008567
8568 /* both TCP and HTTP must check switching rules */
8569 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008570
8571 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008572 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008573 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8574 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008575 if (curproxy->mode == PR_MODE_HTTP) {
8576 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8577 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8578 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008579 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008580 }
8581
8582 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008583 if (curproxy->tcp_req.inspect_delay ||
8584 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8585 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8586
Emeric Brun97679e72010-09-23 17:56:44 +02008587 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8588 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8589
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008590 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008591 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008592 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008593 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008594
8595 /* If the backend does requires RDP cookie persistence, we have to
8596 * enable the corresponding analyser.
8597 */
8598 if (curproxy->options2 & PR_O2_RDPC_PRST)
8599 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008600
8601 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008602 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008603 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8604 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008605 if (curproxy->mode == PR_MODE_HTTP) {
8606 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8607 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8608 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008609 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008610 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008611 }
8612
8613 /***********************************************************/
8614 /* At this point, target names have already been resolved. */
8615 /***********************************************************/
8616
8617 /* Check multi-process mode compatibility */
8618
8619 if (global.nbproc > 1 && global.stats_fe) {
8620 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8621 unsigned long mask;
8622
8623 mask = nbits(global.nbproc);
8624 if (global.stats_fe->bind_proc)
8625 mask &= global.stats_fe->bind_proc;
8626
8627 if (bind_conf->bind_proc)
8628 mask &= bind_conf->bind_proc;
8629
8630 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008631 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008632 break;
8633 }
8634 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8635 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");
8636 }
8637 }
8638
8639 /* Make each frontend inherit bind-process from its listeners when not specified. */
8640 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8641 if (curproxy->bind_proc)
8642 continue;
8643
8644 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8645 unsigned long mask;
8646
Willy Tarreaue428b082015-05-04 21:57:58 +02008647 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008648 curproxy->bind_proc |= mask;
8649 }
8650
8651 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008652 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008653 }
8654
8655 if (global.stats_fe) {
8656 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8657 unsigned long mask;
8658
Cyril Bonté06181952016-02-24 00:14:54 +01008659 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008660 global.stats_fe->bind_proc |= mask;
8661 }
8662 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008663 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008664 }
8665
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008666 /* propagate bindings from frontends to backends. Don't do it if there
8667 * are any fatal errors as we must not call it with unresolved proxies.
8668 */
8669 if (!cfgerr) {
8670 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8671 if (curproxy->cap & PR_CAP_FE)
8672 propagate_processes(curproxy, NULL);
8673 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008674 }
8675
8676 /* Bind each unbound backend to all processes when not specified. */
8677 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8678 if (curproxy->bind_proc)
8679 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008680 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008681 }
8682
8683 /*******************************************************/
8684 /* At this step, all proxies have a non-null bind_proc */
8685 /*******************************************************/
8686
8687 /* perform the final checks before creating tasks */
8688
8689 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8690 struct listener *listener;
8691 unsigned int next_id;
8692 int nbproc;
8693
David Carliere6c39412015-07-02 07:00:17 +00008694 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008695
Emeric Brunc52962f2012-11-15 18:28:02 +01008696#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008697 /* Configure SSL for each bind line.
8698 * Note: if configuration fails at some point, the ->ctx member
8699 * remains NULL so that listeners can later detach.
8700 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008701 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008702 int alloc_ctx;
8703
Emeric Brunc52962f2012-11-15 18:28:02 +01008704 if (!bind_conf->is_ssl) {
8705 if (bind_conf->default_ctx) {
8706 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8707 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8708 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008709 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008710 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008711 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008712 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008713 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008714 cfgerr++;
8715 continue;
8716 }
8717
Emeric Brun8dc60392014-05-09 13:52:00 +02008718 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008719 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008720 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8721 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");
8722 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008723 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008724 cfgerr++;
8725 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008726 }
8727
Emeric Brunfc0421f2012-09-07 17:30:07 +02008728 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008729 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008730
8731 /* initialize CA variables if the certificates generation is enabled */
8732 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008733 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008734#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008735
Willy Tarreaue6b98942007-10-29 01:09:36 +01008736 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008737 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008738 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008739 if (!listener->luid) {
8740 /* listener ID not set, use automatic numbering with first
8741 * spare entry starting with next_luid.
8742 */
8743 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8744 listener->conf.id.key = listener->luid = next_id;
8745 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008746 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008747 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008748
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008749 /* enable separate counters */
8750 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8751 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008752 if (!listener->name)
8753 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008754 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008755
Willy Tarreaue6b98942007-10-29 01:09:36 +01008756 if (curproxy->options & PR_O_TCP_NOLING)
8757 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008758 if (!listener->maxconn)
8759 listener->maxconn = curproxy->maxconn;
8760 if (!listener->backlog)
8761 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008762 if (!listener->maxaccept)
8763 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8764
8765 /* we want to have an optimal behaviour on single process mode to
8766 * maximize the work at once, but in multi-process we want to keep
8767 * some fairness between processes, so we target half of the max
8768 * number of events to be balanced over all the processes the proxy
8769 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8770 * used to disable the limit.
8771 */
8772 if (listener->maxaccept > 0) {
8773 if (nbproc > 1)
8774 listener->maxaccept = (listener->maxaccept + 1) / 2;
8775 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8776 }
8777
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008778 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008779 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008780 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008781 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008782
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008783 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8784 listener->options |= LI_O_TCP_RULES;
8785
Willy Tarreaude3041d2010-05-31 10:56:17 +02008786 if (curproxy->mon_mask.s_addr)
8787 listener->options |= LI_O_CHK_MONNET;
8788
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008789 /* smart accept mode is automatic in HTTP mode */
8790 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008791 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008792 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8793 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008794 }
8795
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008796 /* Release unused SSL configs */
8797 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8798 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008799 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008800#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008801 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008802 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008803 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008804 free(bind_conf->ca_sign_file);
8805 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008806 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008807 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008808 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008809 if(bind_conf->keys_ref) {
8810 free(bind_conf->keys_ref->filename);
8811 free(bind_conf->keys_ref->tlskeys);
8812 free(bind_conf->keys_ref);
8813 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008814#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008815 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008816
Willy Tarreau102df612014-05-07 23:56:38 +02008817 if (nbproc > 1) {
8818 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008819 int count, maxproc = 0;
8820
8821 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008822 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008823 if (count > maxproc)
8824 maxproc = count;
8825 }
8826 /* backends have 0, frontends have 1 or more */
8827 if (maxproc != 1)
8828 Warning("Proxy '%s': in multi-process mode, stats will be"
8829 " limited to process assigned to the current request.\n",
8830 curproxy->id);
8831
Willy Tarreau102df612014-05-07 23:56:38 +02008832 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8833 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8834 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008835 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008836 }
Willy Tarreau102df612014-05-07 23:56:38 +02008837 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8838 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8839 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008840 }
8841 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008842
8843 /* create the task associated with the proxy */
8844 curproxy->task = task_new();
8845 if (curproxy->task) {
8846 curproxy->task->context = curproxy;
8847 curproxy->task->process = manage_proxy;
8848 /* no need to queue, it will be done automatically if some
8849 * listener gets limited.
8850 */
8851 curproxy->task->expire = TICK_ETERNITY;
8852 } else {
8853 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8854 curproxy->id);
8855 cfgerr++;
8856 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008857 }
8858
Willy Tarreaufbb78422011-06-05 15:38:35 +02008859 /* automatically compute fullconn if not set. We must not do it in the
8860 * loop above because cross-references are not yet fully resolved.
8861 */
8862 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8863 /* If <fullconn> is not set, let's set it to 10% of the sum of
8864 * the possible incoming frontend's maxconns.
8865 */
8866 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8867 struct proxy *fe;
8868 int total = 0;
8869
8870 /* sum up the number of maxconns of frontends which
8871 * reference this backend at least once or which are
8872 * the same one ('listen').
8873 */
8874 for (fe = proxy; fe; fe = fe->next) {
8875 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008876 int found = 0;
8877
8878 if (!(fe->cap & PR_CAP_FE))
8879 continue;
8880
8881 if (fe == curproxy) /* we're on a "listen" instance */
8882 found = 1;
8883
8884 if (fe->defbe.be == curproxy) /* "default_backend" */
8885 found = 1;
8886
8887 /* check if a "use_backend" rule matches */
8888 if (!found) {
8889 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008890 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008891 found = 1;
8892 break;
8893 }
8894 }
8895 }
8896
Willy Tarreaufbb78422011-06-05 15:38:35 +02008897 /* now we've checked all possible ways to reference a backend
8898 * from a frontend.
8899 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008900 if (!found)
8901 continue;
8902 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008903 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008904 /* we have the sum of the maxconns in <total>. We only
8905 * keep 10% of that sum to set the default fullconn, with
8906 * a hard minimum of 1 (to avoid a divide by zero).
8907 */
8908 curproxy->fullconn = (total + 9) / 10;
8909 if (!curproxy->fullconn)
8910 curproxy->fullconn = 1;
8911 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008912 }
8913
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008914 /*
8915 * Recount currently required checks.
8916 */
8917
8918 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8919 int optnum;
8920
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008921 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8922 if (curproxy->options & cfg_opts[optnum].val)
8923 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008924
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008925 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8926 if (curproxy->options2 & cfg_opts2[optnum].val)
8927 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008928 }
8929
Willy Tarreau0fca4832015-05-01 19:12:05 +02008930 /* compute the required process bindings for the peers */
8931 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8932 if (curproxy->table.peers.p)
8933 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8934
Willy Tarreau122541c2011-09-07 21:24:49 +02008935 if (peers) {
8936 struct peers *curpeers = peers, **last;
8937 struct peer *p, *pb;
8938
Willy Tarreau1e273012015-05-01 19:15:17 +02008939 /* Remove all peers sections which don't have a valid listener,
8940 * which are not used by any table, or which are bound to more
8941 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008942 */
8943 last = &peers;
8944 while (*last) {
8945 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008946
8947 if (curpeers->state == PR_STSTOPPED) {
8948 /* the "disabled" keyword was present */
8949 if (curpeers->peers_fe)
8950 stop_proxy(curpeers->peers_fe);
8951 curpeers->peers_fe = NULL;
8952 }
8953 else if (!curpeers->peers_fe) {
8954 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8955 curpeers->id, localpeer);
8956 }
David Carliere6c39412015-07-02 07:00:17 +00008957 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008958 /* either it's totally stopped or too much used */
8959 if (curpeers->peers_fe->bind_proc) {
8960 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008961 "running in different processes (%d different ones). "
8962 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008963 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008964 cfgerr++;
8965 }
8966 stop_proxy(curpeers->peers_fe);
8967 curpeers->peers_fe = NULL;
8968 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008969 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008970 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008971 last = &curpeers->next;
8972 continue;
8973 }
8974
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008975 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008976 p = curpeers->remote;
8977 while (p) {
8978 pb = p->next;
8979 free(p->id);
8980 free(p);
8981 p = pb;
8982 }
8983
8984 /* Destroy and unlink this curpeers section.
8985 * Note: curpeers is backed up into *last.
8986 */
8987 free(curpeers->id);
8988 curpeers = curpeers->next;
8989 free(*last);
8990 *last = curpeers;
8991 }
8992 }
8993
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008994 /* initialize stick-tables on backend capable proxies. This must not
8995 * be done earlier because the data size may be discovered while parsing
8996 * other proxies.
8997 */
8998 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8999 if (curproxy->state == PR_STSTOPPED)
9000 continue;
9001
9002 if (!stktable_init(&curproxy->table)) {
9003 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9004 cfgerr++;
9005 }
9006 }
9007
Simon Horman0d16a402015-01-30 11:22:58 +09009008 if (mailers) {
9009 struct mailers *curmailers = mailers, **last;
9010 struct mailer *m, *mb;
9011
9012 /* Remove all mailers sections which don't have a valid listener.
9013 * This can happen when a mailers section is never referenced.
9014 */
9015 last = &mailers;
9016 while (*last) {
9017 curmailers = *last;
9018 if (curmailers->users) {
9019 last = &curmailers->next;
9020 continue;
9021 }
9022
9023 Warning("Removing incomplete section 'mailers %s'.\n",
9024 curmailers->id);
9025
9026 m = curmailers->mailer_list;
9027 while (m) {
9028 mb = m->next;
9029 free(m->id);
9030 free(m);
9031 m = mb;
9032 }
9033
9034 /* Destroy and unlink this curmailers section.
9035 * Note: curmailers is backed up into *last.
9036 */
9037 free(curmailers->id);
9038 curmailers = curmailers->next;
9039 free(*last);
9040 *last = curmailers;
9041 }
9042 }
9043
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009044 /* Update server_state_file_name to backend name if backend is supposed to use
9045 * a server-state file locally defined and none has been provided */
9046 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9047 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9048 curproxy->server_state_file_name == NULL)
9049 curproxy->server_state_file_name = strdup(curproxy->id);
9050 }
9051
Willy Tarreau34eb6712011-10-24 18:15:04 +02009052 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009053 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009054 MEM_F_SHARED);
9055
Willy Tarreaubb925012009-07-23 13:36:36 +02009056 if (cfgerr > 0)
9057 err_code |= ERR_ALERT | ERR_FATAL;
9058 out:
9059 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009060}
9061
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009062/*
9063 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9064 * parsing sessions.
9065 */
9066void cfg_register_keywords(struct cfg_kw_list *kwl)
9067{
9068 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9069}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009070
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009071/*
9072 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9073 */
9074void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9075{
9076 LIST_DEL(&kwl->list);
9077 LIST_INIT(&kwl->list);
9078}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009079
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009080/* this function register new section in the haproxy configuration file.
9081 * <section_name> is the name of this new section and <section_parser>
9082 * is the called parser. If two section declaration have the same name,
9083 * only the first declared is used.
9084 */
9085int cfg_register_section(char *section_name,
9086 int (*section_parser)(const char *, int, char **, int))
9087{
9088 struct cfg_section *cs;
9089
9090 cs = calloc(1, sizeof(*cs));
9091 if (!cs) {
9092 Alert("register section '%s': out of memory.\n", section_name);
9093 return 0;
9094 }
9095
9096 cs->section_name = section_name;
9097 cs->section_parser = section_parser;
9098
9099 LIST_ADDQ(&sections, &cs->list);
9100
9101 return 1;
9102}
9103
Willy Tarreaubaaee002006-06-26 02:48:02 +02009104/*
David Carlier845efb52015-09-25 11:49:18 +01009105 * free all config section entries
9106 */
9107void cfg_unregister_sections(void)
9108{
9109 struct cfg_section *cs, *ics;
9110
9111 list_for_each_entry_safe(cs, ics, &sections, list) {
9112 LIST_DEL(&cs->list);
9113 free(cs);
9114 }
9115}
9116
9117/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009118 * Local variables:
9119 * c-indent-level: 8
9120 * c-basic-offset: 8
9121 * End:
9122 */