blob: 99e97c7de551978ef422a8fef2957c19a3893068 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020048#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010050#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020051#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090052#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020053#include <types/dns.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020054
Willy Tarreaueb0c6142007-05-07 00:53:22 +020055#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010056#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020058#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020059#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020060#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020061#include <proto/dumpstats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020062#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020063#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020064#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020065#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010066#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020067#include <proto/lb_fwlc.h>
68#include <proto/lb_fwrr.h>
69#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020070#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020071#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020072#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010073#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020074#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010075#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010076#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020077#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020078#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020079#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020080#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020081#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020082#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020083#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010084#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020085
Emeric Brunfc0421f2012-09-07 17:30:07 +020086#ifdef USE_OPENSSL
87#include <types/ssl_sock.h>
88#include <proto/ssl_sock.h>
89#include <proto/shctx.h>
90#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020091
Willy Tarreauf3c69202006-07-09 16:42:34 +020092/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
93 * ssl-hello-chk option to ensure that the remote server speaks SSL.
94 *
95 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
96 */
97const char sslv3_client_hello_pkt[] = {
98 "\x16" /* ContentType : 0x16 = Hanshake */
99 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
100 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
101 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
102 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
103 "\x03\x00" /* Hello Version : 0x0300 = v3 */
104 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
105 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
106 "\x00" /* Session ID length : empty (no session ID) */
107 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
108 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
109 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
110 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
111 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
112 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
113 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
114 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
115 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
116 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
117 "\x00\x38" "\x00\x39" "\x00\x3A"
118 "\x01" /* Compression Length : 0x01 = 1 byte for types */
119 "\x00" /* Compression Type : 0x00 = NULL compression */
120};
121
Willy Tarreau3842f002009-06-14 11:39:52 +0200122/* various keyword modifiers */
123enum kw_mod {
124 KWM_STD = 0, /* normal */
125 KWM_NO, /* "no" prefixed before the keyword */
126 KWM_DEF, /* "default" prefixed before the keyword */
127};
128
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100129/* permit to store configuration section */
130struct cfg_section {
131 struct list list;
132 char *section_name;
133 int (*section_parser)(const char *, int, char **, int);
134};
135
136/* Used to chain configuration sections definitions. This list
137 * stores struct cfg_section
138 */
139struct list sections = LIST_HEAD_INIT(sections);
140
Willy Tarreau13943ab2006-12-31 00:24:10 +0100141/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100143 const char *name;
144 unsigned int val;
145 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100146 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148};
149
150/* proxy->options */
151static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100152{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
154 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
155 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
156 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
157 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
158 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100159 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200160 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200161 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100162 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
164 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
165 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100166 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100167#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100168 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100169#else
170 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100171#endif
172
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100174};
175
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176/* proxy->options2 */
177static const struct cfg_opt cfg_opts2[] =
178{
179#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100180 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
181 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
182 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100183#else
184 { "splice-request", 0, 0, 0, 0 },
185 { "splice-response", 0, 0, 0, 0 },
186 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100187#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100188 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
189 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
190 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
191 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
192 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
193 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
194 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
195 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
196 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400197 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100198 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200199 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200200 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100201 { NULL, 0, 0, 0 }
202};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203
Willy Tarreau6daf3432008-01-22 16:44:08 +0100204static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
206int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100207int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200209/* List head of all known configuration keywords */
210static struct cfg_kw_list cfg_keywords = {
211 .list = LIST_HEAD_INIT(cfg_keywords.list)
212};
213
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214/*
215 * converts <str> to a list of listeners which are dynamically allocated.
216 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
217 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
218 * - <port> is a numerical port from 1 to 65535 ;
219 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
220 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200221 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
222 * not NULL, it must be a valid pointer to either NULL or a freeable area that
223 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200225int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226{
227 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100228 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229 int port, end;
230
231 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200232
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100234 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100235 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236
237 str = next;
238 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100239 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240 *next++ = 0;
241 }
242
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100243 ss2 = str2sa_range(str, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200244 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200245 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100246 if (!ss2)
247 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200248
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100249 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100250 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200251 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100252 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200253 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100255 if (!port || !end) {
256 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
257 goto fail;
258 }
259
Emeric Bruned760922010-10-22 17:59:25 +0200260 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200261 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200262 goto fail;
263 }
264
265 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200266 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200267 goto fail;
268 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200269 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100270 else if (ss2->ss_family == AF_UNSPEC) {
271 socklen_t addr_len;
272
273 /* We want to attach to an already bound fd whose number
274 * is in the addr part of ss2 when cast to sockaddr_in.
275 * Note that by definition there is a single listener.
276 * We still have to determine the address family to
277 * register the correct protocol.
278 */
279 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
280 addr_len = sizeof(*ss2);
281 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
282 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
283 goto fail;
284 }
285
286 port = end = get_host_port(ss2);
287 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100289 /* OK the address looks correct */
290 ss = *ss2;
291
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292 for (; port <= end; port++) {
293 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100294 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200295 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
296 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
297 l->frontend = curproxy;
298 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299
Willy Tarreau40aa0702013-03-10 23:51:38 +0100300 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200302 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100303 l->state = LI_INIT;
304
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100305 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200306 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100307 tcpv4_add_listener(l);
308 }
Emeric Bruned760922010-10-22 17:59:25 +0200309 else if (ss.ss_family == AF_INET6) {
310 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
311 tcpv6_add_listener(l);
312 }
313 else {
Emeric Bruned760922010-10-22 17:59:25 +0200314 uxst_add_listener(l);
315 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200316
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200317 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100318 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319 } /* end for(port) */
320 } /* end while(next) */
321 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200322 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200323 fail:
324 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200325 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200326}
327
William Lallemand6e62fb62015-04-28 16:55:23 +0200328/*
329 * Report a fatal Alert when there is too much arguments
330 * The index is the current keyword in args
331 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
332 * Fill err_code with an ERR_ALERT and an ERR_FATAL
333 */
334int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
335{
336 char *kw = NULL;
337 int i;
338
339 if (!*args[index + maxarg + 1])
340 return 0;
341
342 memprintf(&kw, "%s", args[0]);
343 for (i = 1; i <= index; i++) {
344 memprintf(&kw, "%s %s", kw, args[i]);
345 }
346
347 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
348 free(kw);
349 *err_code |= ERR_ALERT | ERR_FATAL;
350 return 1;
351}
352
353/*
354 * same as alertif_too_many_args_idx with a 0 index
355 */
356int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
357{
358 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
359}
360
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200361/* Report a warning if a rule is placed after a 'tcp-request content' rule.
362 * Return 1 if the warning has been emitted, otherwise 0.
363 */
364int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
365{
366 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
367 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
368 file, line, arg);
369 return 1;
370 }
371 return 0;
372}
373
Willy Tarreau61d18892009-03-31 10:49:21 +0200374/* Report a warning if a rule is placed after a 'block' rule.
375 * Return 1 if the warning has been emitted, otherwise 0.
376 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100377int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200378{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200379 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200380 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
381 file, line, arg);
382 return 1;
383 }
384 return 0;
385}
386
Willy Tarreau5002f572014-04-23 01:32:02 +0200387/* Report a warning if a rule is placed after an 'http_request' rule.
388 * Return 1 if the warning has been emitted, otherwise 0.
389 */
390int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
391{
392 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
393 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
394 file, line, arg);
395 return 1;
396 }
397 return 0;
398}
399
Willy Tarreau61d18892009-03-31 10:49:21 +0200400/* Report a warning if a rule is placed after a reqrewrite rule.
401 * Return 1 if the warning has been emitted, otherwise 0.
402 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 if (proxy->req_exp) {
406 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
407 file, line, arg);
408 return 1;
409 }
410 return 0;
411}
412
413/* Report a warning if a rule is placed after a reqadd rule.
414 * Return 1 if the warning has been emitted, otherwise 0.
415 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100416int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200417{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100418 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200419 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
420 file, line, arg);
421 return 1;
422 }
423 return 0;
424}
425
426/* Report a warning if a rule is placed after a redirect rule.
427 * Return 1 if the warning has been emitted, otherwise 0.
428 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100429int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200430{
431 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
432 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
433 file, line, arg);
434 return 1;
435 }
436 return 0;
437}
438
439/* Report a warning if a rule is placed after a 'use_backend' rule.
440 * Return 1 if the warning has been emitted, otherwise 0.
441 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100442int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200443{
444 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
445 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
446 file, line, arg);
447 return 1;
448 }
449 return 0;
450}
451
Willy Tarreauee445d92014-04-23 01:39:04 +0200452/* Report a warning if a rule is placed after a 'use-server' rule.
453 * Return 1 if the warning has been emitted, otherwise 0.
454 */
455int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
456{
457 if (!LIST_ISEMPTY(&proxy->server_rules)) {
458 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
459 file, line, arg);
460 return 1;
461 }
462 return 0;
463}
464
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200465/* report a warning if a "tcp request connection" rule is dangerously placed */
466int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
467{
468 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
469 warnif_rule_after_block(proxy, file, line, arg) ||
470 warnif_rule_after_http_req(proxy, file, line, arg) ||
471 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
472 warnif_rule_after_reqadd(proxy, file, line, arg) ||
473 warnif_rule_after_redirect(proxy, file, line, arg) ||
474 warnif_rule_after_use_backend(proxy, file, line, arg) ||
475 warnif_rule_after_use_server(proxy, file, line, arg);
476}
477
478/* report a warning if a "tcp request content" rule is dangerously placed */
479int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
480{
481 return warnif_rule_after_block(proxy, file, line, arg) ||
482 warnif_rule_after_http_req(proxy, file, line, arg) ||
483 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
484 warnif_rule_after_reqadd(proxy, file, line, arg) ||
485 warnif_rule_after_redirect(proxy, file, line, arg) ||
486 warnif_rule_after_use_backend(proxy, file, line, arg) ||
487 warnif_rule_after_use_server(proxy, file, line, arg);
488}
489
Willy Tarreau61d18892009-03-31 10:49:21 +0200490/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100491int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200492{
Willy Tarreau5002f572014-04-23 01:32:02 +0200493 return warnif_rule_after_http_req(proxy, file, line, arg) ||
494 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
495 warnif_rule_after_reqadd(proxy, file, line, arg) ||
496 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200497 warnif_rule_after_use_backend(proxy, file, line, arg) ||
498 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200499}
500
501/* report a warning if an http-request rule is dangerously placed */
502int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
503{
Willy Tarreau61d18892009-03-31 10:49:21 +0200504 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
505 warnif_rule_after_reqadd(proxy, file, line, arg) ||
506 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200507 warnif_rule_after_use_backend(proxy, file, line, arg) ||
508 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200509}
510
511/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100512int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200513{
514 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
515 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200516 warnif_rule_after_use_backend(proxy, file, line, arg) ||
517 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200518}
519
520/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100521int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200522{
523 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200524 warnif_rule_after_use_backend(proxy, file, line, arg) ||
525 warnif_rule_after_use_server(proxy, file, line, arg);
526}
527
528/* report a warning if a redirect rule is dangerously placed */
529int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
530{
531 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
532 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200533}
534
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100535/* Report it if a request ACL condition uses some keywords that are incompatible
536 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
537 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
538 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100539 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100540static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100541{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100542 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200543 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100544
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100545 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100546 return 0;
547
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100548 acl = acl_cond_conflicts(cond, where);
549 if (acl) {
550 if (acl->name && *acl->name)
551 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
552 file, line, acl->name, sample_ckp_names(where));
553 else
554 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200555 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100556 return ERR_WARN;
557 }
558 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100559 return 0;
560
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100561 if (acl->name && *acl->name)
562 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200563 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100564 else
565 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200566 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100567 return ERR_WARN;
568}
569
Willy Tarreaubaaee002006-06-26 02:48:02 +0200570/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200571 * parse a line in a <global> section. Returns the error code, 0 if OK, or
572 * any combination of :
573 * - ERR_ABORT: must abort ASAP
574 * - ERR_FATAL: we can continue parsing but not start the service
575 * - ERR_WARN: a warning has been emitted
576 * - ERR_ALERT: an alert has been emitted
577 * Only the two first ones can stop processing, the two others are just
578 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200580int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581{
Willy Tarreau058e9072009-07-20 09:30:05 +0200582 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200583 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200584
585 if (!strcmp(args[0], "global")) { /* new section */
586 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200587 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200590 else if (!strcmp(args[0], "ca-base")) {
591#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200592 if(alertif_too_many_args(1, file, linenum, args, &err_code))
593 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200594 if (global.ca_base != NULL) {
595 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
596 err_code |= ERR_ALERT;
597 goto out;
598 }
599 if (*(args[1]) == 0) {
600 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
601 err_code |= ERR_ALERT | ERR_FATAL;
602 goto out;
603 }
604 global.ca_base = strdup(args[1]);
605#else
606 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
607 err_code |= ERR_ALERT | ERR_FATAL;
608 goto out;
609#endif
610 }
611 else if (!strcmp(args[0], "crt-base")) {
612#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200613 if (alertif_too_many_args(1, file, linenum, args, &err_code))
614 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200615 if (global.crt_base != NULL) {
616 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
617 err_code |= ERR_ALERT;
618 goto out;
619 }
620 if (*(args[1]) == 0) {
621 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
622 err_code |= ERR_ALERT | ERR_FATAL;
623 goto out;
624 }
625 global.crt_base = strdup(args[1]);
626#else
627 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
628 err_code |= ERR_ALERT | ERR_FATAL;
629 goto out;
630#endif
631 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200632 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200633 if (alertif_too_many_args(0, file, linenum, args, &err_code))
634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 global.mode |= MODE_DAEMON;
636 }
637 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200638 if (alertif_too_many_args(0, file, linenum, args, &err_code))
639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200640 global.mode |= MODE_DEBUG;
641 }
642 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200643 if (alertif_too_many_args(0, file, linenum, args, &err_code))
644 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100645 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200646 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200647 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200648 if (alertif_too_many_args(0, file, linenum, args, &err_code))
649 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100650 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200651 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200653 if (alertif_too_many_args(0, file, linenum, args, &err_code))
654 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100655 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100657 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200658 if (alertif_too_many_args(0, file, linenum, args, &err_code))
659 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100660 global.tune.options &= ~GTUNE_USE_SPLICE;
661 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200662 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200663 if (alertif_too_many_args(0, file, linenum, args, &err_code))
664 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200665 global.tune.options &= ~GTUNE_USE_GAI;
666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200667 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200668 if (alertif_too_many_args(0, file, linenum, args, &err_code))
669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 global.mode |= MODE_QUIET;
671 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200672 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200673 if (alertif_too_many_args(1, file, linenum, args, &err_code))
674 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200675 if (global.tune.maxpollevents != 0) {
676 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT;
678 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200679 }
680 if (*(args[1]) == 0) {
681 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200682 err_code |= ERR_ALERT | ERR_FATAL;
683 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200684 }
685 global.tune.maxpollevents = atol(args[1]);
686 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100687 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200688 if (alertif_too_many_args(1, file, linenum, args, &err_code))
689 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100690 if (global.tune.maxaccept != 0) {
691 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT;
693 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100694 }
695 if (*(args[1]) == 0) {
696 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200697 err_code |= ERR_ALERT | ERR_FATAL;
698 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100699 }
700 global.tune.maxaccept = atol(args[1]);
701 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200702 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200703 if (alertif_too_many_args(1, file, linenum, args, &err_code))
704 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200705 if (*(args[1]) == 0) {
706 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
707 err_code |= ERR_ALERT | ERR_FATAL;
708 goto out;
709 }
710 global.tune.chksize = atol(args[1]);
711 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100712 else if (!strcmp(args[0], "tune.recv_enough")) {
713 if (alertif_too_many_args(1, file, linenum, args, &err_code))
714 goto out;
715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 global.tune.recv_enough = atol(args[1]);
721 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200722#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200723 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200724 if (alertif_too_many_args(0, file, linenum, args, &err_code))
725 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200726 global.tune.sslprivatecache = 1;
727 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100728 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200729 if (alertif_too_many_args(1, file, linenum, args, &err_code))
730 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200731 if (*(args[1]) == 0) {
732 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
733 err_code |= ERR_ALERT | ERR_FATAL;
734 goto out;
735 }
736 global.tune.sslcachesize = atol(args[1]);
737 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100738 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
739 unsigned int ssllifetime;
740 const char *res;
741
William Lallemand1a748ae2015-05-19 16:37:23 +0200742 if (alertif_too_many_args(1, file, linenum, args, &err_code))
743 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100744 if (*(args[1]) == 0) {
745 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
746 err_code |= ERR_ALERT | ERR_FATAL;
747 goto out;
748 }
749
750 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
751 if (res) {
752 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
753 file, linenum, *res, args[0]);
754 err_code |= ERR_ALERT | ERR_FATAL;
755 goto out;
756 }
757
758 global.tune.ssllifetime = ssllifetime;
759 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100760 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200761 if (alertif_too_many_args(1, file, linenum, args, &err_code))
762 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100763 if (*(args[1]) == 0) {
764 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
765 err_code |= ERR_ALERT | ERR_FATAL;
766 goto out;
767 }
768 global.tune.ssl_max_record = atol(args[1]);
769 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200770#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200771 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200772 if (alertif_too_many_args(1, file, linenum, args, &err_code))
773 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200774 if (*(args[1]) == 0) {
775 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
776 err_code |= ERR_ALERT | ERR_FATAL;
777 goto out;
778 }
779 global.tune.ssl_default_dh_param = atol(args[1]);
780 if (global.tune.ssl_default_dh_param < 1024) {
781 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
782 err_code |= ERR_ALERT | ERR_FATAL;
783 goto out;
784 }
785 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200786#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200787 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
788 if (alertif_too_many_args(1, file, linenum, args, &err_code))
789 goto out;
790 if (*(args[1]) == 0) {
791 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
794 }
795 global.tune.ssl_ctx_cache = atoi(args[1]);
796 if (global.tune.ssl_ctx_cache < 0) {
797 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
798 file, linenum, args[0]);
799 err_code |= ERR_ALERT | ERR_FATAL;
800 goto out;
801 }
802 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200803#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100804 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200805 if (alertif_too_many_args(1, file, linenum, args, &err_code))
806 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
811 }
812 global.tune.buf_limit = atol(args[1]);
813 if (global.tune.buf_limit) {
814 if (global.tune.buf_limit < 3)
815 global.tune.buf_limit = 3;
816 if (global.tune.buf_limit <= global.tune.reserved_bufs)
817 global.tune.buf_limit = global.tune.reserved_bufs + 1;
818 }
819 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100820 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200821 if (alertif_too_many_args(1, file, linenum, args, &err_code))
822 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100823 if (*(args[1]) == 0) {
824 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
827 }
828 global.tune.reserved_bufs = atol(args[1]);
829 if (global.tune.reserved_bufs < 2)
830 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100831 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
832 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100833 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200834 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200835 if (alertif_too_many_args(1, file, linenum, args, &err_code))
836 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200837 if (*(args[1]) == 0) {
838 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
839 err_code |= ERR_ALERT | ERR_FATAL;
840 goto out;
841 }
842 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200843 if (global.tune.bufsize <= 0) {
844 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
845 err_code |= ERR_ALERT | ERR_FATAL;
846 goto out;
847 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100848 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100849 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200850 }
851 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200852 if (alertif_too_many_args(1, file, linenum, args, &err_code))
853 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200854 if (*(args[1]) == 0) {
855 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200860 if (global.tune.maxrewrite < 0) {
861 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200865 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100866 else if (!strcmp(args[0], "tune.idletimer")) {
867 unsigned int idle;
868 const char *res;
869
William Lallemand1a748ae2015-05-19 16:37:23 +0200870 if (alertif_too_many_args(1, file, linenum, args, &err_code))
871 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100872 if (*(args[1]) == 0) {
873 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
874 err_code |= ERR_ALERT | ERR_FATAL;
875 goto out;
876 }
877
878 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
879 if (res) {
880 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
881 file, linenum, *res, args[0]);
882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
884 }
885
886 if (idle > 65535) {
887 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
888 err_code |= ERR_ALERT | ERR_FATAL;
889 goto out;
890 }
891 global.tune.idle_timer = idle;
892 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100893 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200894 if (alertif_too_many_args(1, file, linenum, args, &err_code))
895 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100896 if (global.tune.client_rcvbuf != 0) {
897 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
898 err_code |= ERR_ALERT;
899 goto out;
900 }
901 if (*(args[1]) == 0) {
902 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
903 err_code |= ERR_ALERT | ERR_FATAL;
904 goto out;
905 }
906 global.tune.client_rcvbuf = atol(args[1]);
907 }
908 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200909 if (alertif_too_many_args(1, file, linenum, args, &err_code))
910 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100911 if (global.tune.server_rcvbuf != 0) {
912 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
913 err_code |= ERR_ALERT;
914 goto out;
915 }
916 if (*(args[1]) == 0) {
917 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
918 err_code |= ERR_ALERT | ERR_FATAL;
919 goto out;
920 }
921 global.tune.server_rcvbuf = atol(args[1]);
922 }
923 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200924 if (alertif_too_many_args(1, file, linenum, args, &err_code))
925 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100926 if (global.tune.client_sndbuf != 0) {
927 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
928 err_code |= ERR_ALERT;
929 goto out;
930 }
931 if (*(args[1]) == 0) {
932 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
935 }
936 global.tune.client_sndbuf = atol(args[1]);
937 }
938 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200939 if (alertif_too_many_args(1, file, linenum, args, &err_code))
940 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100941 if (global.tune.server_sndbuf != 0) {
942 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
943 err_code |= ERR_ALERT;
944 goto out;
945 }
946 if (*(args[1]) == 0) {
947 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
948 err_code |= ERR_ALERT | ERR_FATAL;
949 goto out;
950 }
951 global.tune.server_sndbuf = atol(args[1]);
952 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200953 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200954 if (alertif_too_many_args(1, file, linenum, args, &err_code))
955 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200956 if (*(args[1]) == 0) {
957 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
958 err_code |= ERR_ALERT | ERR_FATAL;
959 goto out;
960 }
961 global.tune.pipesize = atol(args[1]);
962 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100963 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200964 if (alertif_too_many_args(1, file, linenum, args, &err_code))
965 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100966 if (*(args[1]) == 0) {
967 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
968 err_code |= ERR_ALERT | ERR_FATAL;
969 goto out;
970 }
971 global.tune.cookie_len = atol(args[1]) + 1;
972 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200973 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200974 if (alertif_too_many_args(1, file, linenum, args, &err_code))
975 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200976 if (*(args[1]) == 0) {
977 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
978 err_code |= ERR_ALERT | ERR_FATAL;
979 goto out;
980 }
981 global.tune.max_http_hdr = atol(args[1]);
982 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100983 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
984#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200985 if (alertif_too_many_args(1, file, linenum, args, &err_code))
986 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100987 if (*args[1]) {
988 global.tune.zlibmemlevel = atoi(args[1]);
989 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
990 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
991 file, linenum, args[0]);
992 err_code |= ERR_ALERT | ERR_FATAL;
993 goto out;
994 }
995 } else {
996 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
997 file, linenum, args[0]);
998 err_code |= ERR_ALERT | ERR_FATAL;
999 goto out;
1000 }
1001#else
1002 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005#endif
1006 }
1007 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
1008#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001009 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1010 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001011 if (*args[1]) {
1012 global.tune.zlibwindowsize = atoi(args[1]);
1013 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
1014 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1015 file, linenum, args[0]);
1016 err_code |= ERR_ALERT | ERR_FATAL;
1017 goto out;
1018 }
1019 } else {
1020 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1021 file, linenum, args[0]);
1022 err_code |= ERR_ALERT | ERR_FATAL;
1023 goto out;
1024 }
1025#else
1026 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1027 err_code |= ERR_ALERT | ERR_FATAL;
1028 goto out;
1029#endif
1030 }
William Lallemandf3747832012-11-09 12:33:10 +01001031 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001032 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1033 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001034 if (*args[1]) {
1035 global.tune.comp_maxlevel = atoi(args[1]);
1036 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1037 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1038 file, linenum, args[0]);
1039 err_code |= ERR_ALERT | ERR_FATAL;
1040 goto out;
1041 }
1042 } else {
1043 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1044 file, linenum, args[0]);
1045 err_code |= ERR_ALERT | ERR_FATAL;
1046 goto out;
1047 }
1048 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001049 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1050 if (*args[1]) {
1051 global.tune.pattern_cache = atoi(args[1]);
1052 if (global.tune.pattern_cache < 0) {
1053 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1054 file, linenum, args[0]);
1055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
1057 }
1058 } else {
1059 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1060 file, linenum, args[0]);
1061 err_code |= ERR_ALERT | ERR_FATAL;
1062 goto out;
1063 }
1064 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001066 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001069 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001070 err_code |= ERR_ALERT;
1071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 }
1073 if (*(args[1]) == 0) {
1074 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001075 err_code |= ERR_ALERT | ERR_FATAL;
1076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001077 }
1078 global.uid = atol(args[1]);
1079 }
1080 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001081 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001083 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001084 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001085 err_code |= ERR_ALERT;
1086 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 }
1088 if (*(args[1]) == 0) {
1089 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT | ERR_FATAL;
1091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 }
1093 global.gid = atol(args[1]);
1094 }
Simon Horman98637e52014-06-20 12:30:16 +09001095 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001096 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1097 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001098 global.external_check = 1;
1099 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001100 /* user/group name handling */
1101 else if (!strcmp(args[0], "user")) {
1102 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001103 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1104 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001105 if (global.uid != 0) {
1106 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001107 err_code |= ERR_ALERT;
1108 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001109 }
1110 errno = 0;
1111 ha_user = getpwnam(args[1]);
1112 if (ha_user != NULL) {
1113 global.uid = (int)ha_user->pw_uid;
1114 }
1115 else {
1116 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001118 }
1119 }
1120 else if (!strcmp(args[0], "group")) {
1121 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001122 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1123 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001124 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001125 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT;
1127 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001128 }
1129 errno = 0;
1130 ha_group = getgrnam(args[1]);
1131 if (ha_group != NULL) {
1132 global.gid = (int)ha_group->gr_gid;
1133 }
1134 else {
1135 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001137 }
1138 }
1139 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001140 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001141 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143 if (*(args[1]) == 0) {
1144 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001145 err_code |= ERR_ALERT | ERR_FATAL;
1146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147 }
1148 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001149 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1150 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1151 file, linenum, args[0], LONGBITS, global.nbproc);
1152 err_code |= ERR_ALERT | ERR_FATAL;
1153 goto out;
1154 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001155 }
1156 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001157 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001159 if (global.maxconn != 0) {
1160 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001161 err_code |= ERR_ALERT;
1162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163 }
1164 if (*(args[1]) == 0) {
1165 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001166 err_code |= ERR_ALERT | ERR_FATAL;
1167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 }
1169 global.maxconn = atol(args[1]);
1170#ifdef SYSTEM_MAXCONN
1171 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1172 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
1173 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001174 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001175 }
1176#endif /* SYSTEM_MAXCONN */
1177 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001178 else if (!strcmp(args[0], "maxsslconn")) {
1179#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001180 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1181 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001182 if (*(args[1]) == 0) {
1183 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 goto out;
1186 }
1187 global.maxsslconn = atol(args[1]);
1188#else
Emeric Brun0914df82012-10-02 18:45:42 +02001189 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1190 err_code |= ERR_ALERT | ERR_FATAL;
1191 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001192#endif
1193 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001194 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1195#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001196 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1197 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001198 if (*(args[1]) == 0) {
1199 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1200 err_code |= ERR_ALERT | ERR_FATAL;
1201 goto out;
1202 }
1203 free(global.listen_default_ciphers);
1204 global.listen_default_ciphers = strdup(args[1]);
1205#else
1206 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1207 err_code |= ERR_ALERT | ERR_FATAL;
1208 goto out;
1209#endif
1210 }
1211 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1212#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001213 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1214 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001215 if (*(args[1]) == 0) {
1216 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1217 err_code |= ERR_ALERT | ERR_FATAL;
1218 goto out;
1219 }
1220 free(global.connect_default_ciphers);
1221 global.connect_default_ciphers = strdup(args[1]);
1222#else
1223 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1224 err_code |= ERR_ALERT | ERR_FATAL;
1225 goto out;
1226#endif
1227 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001228#ifdef USE_OPENSSL
1229#ifndef OPENSSL_NO_DH
1230 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1231 if (*(args[1]) == 0) {
1232 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1233 err_code |= ERR_ALERT | ERR_FATAL;
1234 goto out;
1235 }
1236 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1237 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1238 err_code |= ERR_ALERT | ERR_FATAL;
1239 goto out;
1240 }
1241 }
1242#endif
1243#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001244 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001245 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1246 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001247 if (*(args[1]) == 0) {
1248 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
1251 }
1252 if (strcmp(args[1],"none") == 0)
1253 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1254 else if (strcmp(args[1],"required") == 0)
1255 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1256 else {
1257 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1258 err_code |= ERR_ALERT | ERR_FATAL;
1259 goto out;
1260 }
1261 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001262 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001263 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1264 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001265 if (global.cps_lim != 0) {
1266 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1267 err_code |= ERR_ALERT;
1268 goto out;
1269 }
1270 if (*(args[1]) == 0) {
1271 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1272 err_code |= ERR_ALERT | ERR_FATAL;
1273 goto out;
1274 }
1275 global.cps_lim = atol(args[1]);
1276 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001277 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001278 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1279 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001280 if (global.sps_lim != 0) {
1281 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1282 err_code |= ERR_ALERT;
1283 goto out;
1284 }
1285 if (*(args[1]) == 0) {
1286 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1287 err_code |= ERR_ALERT | ERR_FATAL;
1288 goto out;
1289 }
1290 global.sps_lim = atol(args[1]);
1291 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001292 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001293 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1294 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001295 if (global.ssl_lim != 0) {
1296 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1297 err_code |= ERR_ALERT;
1298 goto out;
1299 }
1300 if (*(args[1]) == 0) {
1301 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1302 err_code |= ERR_ALERT | ERR_FATAL;
1303 goto out;
1304 }
1305 global.ssl_lim = atol(args[1]);
1306 }
William Lallemandd85f9172012-11-09 17:05:39 +01001307 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001308 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1309 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001310 if (*(args[1]) == 0) {
1311 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1312 err_code |= ERR_ALERT | ERR_FATAL;
1313 goto out;
1314 }
1315 global.comp_rate_lim = atoi(args[1]) * 1024;
1316 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001317 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001318 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1319 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001320 if (global.maxpipes != 0) {
1321 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001322 err_code |= ERR_ALERT;
1323 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001324 }
1325 if (*(args[1]) == 0) {
1326 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001327 err_code |= ERR_ALERT | ERR_FATAL;
1328 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001329 }
1330 global.maxpipes = atol(args[1]);
1331 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001332 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001333 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1334 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001335 if (*(args[1]) == 0) {
1336 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1337 err_code |= ERR_ALERT | ERR_FATAL;
1338 goto out;
1339 }
William Lallemande3a7d992012-11-20 11:25:20 +01001340 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001341 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001342 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001343 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1344 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001345 if (*(args[1]) == 0) {
1346 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1347 err_code |= ERR_ALERT | ERR_FATAL;
1348 goto out;
1349 }
1350 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001351 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001352 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1353 err_code |= ERR_ALERT | ERR_FATAL;
1354 goto out;
1355 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001356 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001357
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001359 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001361 if (global.rlimit_nofile != 0) {
1362 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001363 err_code |= ERR_ALERT;
1364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001365 }
1366 if (*(args[1]) == 0) {
1367 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001368 err_code |= ERR_ALERT | ERR_FATAL;
1369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001370 }
1371 global.rlimit_nofile = atol(args[1]);
1372 }
1373 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001374 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 if (global.chroot != NULL) {
1377 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001378 err_code |= ERR_ALERT;
1379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380 }
1381 if (*(args[1]) == 0) {
1382 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001383 err_code |= ERR_ALERT | ERR_FATAL;
1384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 }
1386 global.chroot = strdup(args[1]);
1387 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001388 else if (!strcmp(args[0], "description")) {
1389 int i, len=0;
1390 char *d;
1391
1392 if (!*args[1]) {
1393 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1394 file, linenum, args[0]);
1395 err_code |= ERR_ALERT | ERR_FATAL;
1396 goto out;
1397 }
1398
Willy Tarreau348acfe2014-04-14 15:00:39 +02001399 for (i = 1; *args[i]; i++)
1400 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001401
1402 if (global.desc)
1403 free(global.desc);
1404
1405 global.desc = d = (char *)calloc(1, len);
1406
Willy Tarreau348acfe2014-04-14 15:00:39 +02001407 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1408 for (i = 2; *args[i]; i++)
1409 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001410 }
1411 else if (!strcmp(args[0], "node")) {
1412 int i;
1413 char c;
1414
William Lallemand1a748ae2015-05-19 16:37:23 +02001415 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1416 goto out;
1417
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001418 for (i=0; args[1][i]; i++) {
1419 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001420 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1421 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001422 break;
1423 }
1424
1425 if (!i || args[1][i]) {
1426 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1427 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1428 file, linenum, args[0]);
1429 err_code |= ERR_ALERT | ERR_FATAL;
1430 goto out;
1431 }
1432
1433 if (global.node)
1434 free(global.node);
1435
1436 global.node = strdup(args[1]);
1437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001439 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001441 if (global.pidfile != NULL) {
1442 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001443 err_code |= ERR_ALERT;
1444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445 }
1446 if (*(args[1]) == 0) {
1447 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001448 err_code |= ERR_ALERT | ERR_FATAL;
1449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450 }
1451 global.pidfile = strdup(args[1]);
1452 }
Emeric Bruned760922010-10-22 17:59:25 +02001453 else if (!strcmp(args[0], "unix-bind")) {
1454 int cur_arg = 1;
1455 while (*(args[cur_arg])) {
1456 if (!strcmp(args[cur_arg], "prefix")) {
1457 if (global.unix_bind.prefix != NULL) {
1458 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1459 err_code |= ERR_ALERT;
1460 cur_arg += 2;
1461 continue;
1462 }
1463
1464 if (*(args[cur_arg+1]) == 0) {
1465 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1466 err_code |= ERR_ALERT | ERR_FATAL;
1467 goto out;
1468 }
1469 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1470 cur_arg += 2;
1471 continue;
1472 }
1473
1474 if (!strcmp(args[cur_arg], "mode")) {
1475
1476 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1477 cur_arg += 2;
1478 continue;
1479 }
1480
1481 if (!strcmp(args[cur_arg], "uid")) {
1482
1483 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1484 cur_arg += 2;
1485 continue;
1486 }
1487
1488 if (!strcmp(args[cur_arg], "gid")) {
1489
1490 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1491 cur_arg += 2;
1492 continue;
1493 }
1494
1495 if (!strcmp(args[cur_arg], "user")) {
1496 struct passwd *user;
1497
1498 user = getpwnam(args[cur_arg + 1]);
1499 if (!user) {
1500 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1501 file, linenum, args[0], args[cur_arg + 1 ]);
1502 err_code |= ERR_ALERT | ERR_FATAL;
1503 goto out;
1504 }
1505
1506 global.unix_bind.ux.uid = user->pw_uid;
1507 cur_arg += 2;
1508 continue;
1509 }
1510
1511 if (!strcmp(args[cur_arg], "group")) {
1512 struct group *group;
1513
1514 group = getgrnam(args[cur_arg + 1]);
1515 if (!group) {
1516 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1517 file, linenum, args[0], args[cur_arg + 1 ]);
1518 err_code |= ERR_ALERT | ERR_FATAL;
1519 goto out;
1520 }
1521
1522 global.unix_bind.ux.gid = group->gr_gid;
1523 cur_arg += 2;
1524 continue;
1525 }
1526
Willy Tarreaub48f9582011-09-05 01:17:06 +02001527 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001528 file, linenum, args[0]);
1529 err_code |= ERR_ALERT | ERR_FATAL;
1530 goto out;
1531 }
1532 }
William Lallemand0f99e342011-10-12 17:50:54 +02001533 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1534 /* delete previous herited or defined syslog servers */
1535 struct logsrv *back;
1536 struct logsrv *tmp;
1537
1538 if (*(args[1]) != 0) {
1539 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1540 err_code |= ERR_ALERT | ERR_FATAL;
1541 goto out;
1542 }
1543
1544 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1545 LIST_DEL(&tmp->list);
1546 free(tmp);
1547 }
1548 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001549 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001550 struct sockaddr_storage *sk;
1551 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001552 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001553 int arg = 0;
1554 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001555
William Lallemand1a748ae2015-05-19 16:37:23 +02001556 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1557 goto out;
1558
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 if (*(args[1]) == 0 || *(args[2]) == 0) {
1560 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001561 err_code |= ERR_ALERT | ERR_FATAL;
1562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563 }
William Lallemand0f99e342011-10-12 17:50:54 +02001564
1565 logsrv = calloc(1, sizeof(struct logsrv));
1566
Willy Tarreau18324f52014-06-27 18:10:07 +02001567 /* just after the address, a length may be specified */
1568 if (strcmp(args[arg+2], "len") == 0) {
1569 len = atoi(args[arg+3]);
1570 if (len < 80 || len > 65535) {
1571 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1572 file, linenum, args[arg+3]);
1573 err_code |= ERR_ALERT | ERR_FATAL;
1574 goto out;
1575 }
1576 logsrv->maxlen = len;
1577
1578 /* skip these two args */
1579 arg += 2;
1580 }
1581 else
1582 logsrv->maxlen = MAX_SYSLOG_LEN;
1583
1584 if (logsrv->maxlen > global.max_syslog_len) {
1585 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02001586 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02001587 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001588 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02001589 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001590 }
1591
Dragan Dosen1322d092015-09-22 16:05:32 +02001592 /* after the length, a format may be specified */
1593 if (strcmp(args[arg+2], "format") == 0) {
1594 logsrv->format = get_log_format(args[arg+3]);
1595 if (logsrv->format < 0) {
1596 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1597 err_code |= ERR_ALERT | ERR_FATAL;
1598 goto out;
1599 }
1600
1601 /* skip these two args */
1602 arg += 2;
1603 }
1604
William Lallemand1a748ae2015-05-19 16:37:23 +02001605 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1606 goto out;
1607
Willy Tarreau18324f52014-06-27 18:10:07 +02001608 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001609 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001610 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001611 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001612 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001613 }
1614
William Lallemand0f99e342011-10-12 17:50:54 +02001615 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001616 if (*(args[arg+3])) {
1617 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001618 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001619 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001620 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001621 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622 }
1623 }
1624
William Lallemand0f99e342011-10-12 17:50:54 +02001625 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001626 if (*(args[arg+4])) {
1627 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001628 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001629 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001630 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001631 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001632 }
1633 }
1634
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001635 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001636 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001637 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001638 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001639 free(logsrv);
1640 goto out;
1641 }
1642 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001643
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001644 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001645 if (port1 != port2) {
1646 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1647 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001648 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001649 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001650 goto out;
1651 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001652
William Lallemand0f99e342011-10-12 17:50:54 +02001653 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001654 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001655 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001656 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001657
William Lallemand0f99e342011-10-12 17:50:54 +02001658 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001659 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001660 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1661 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001662
1663 if (global.log_send_hostname != NULL) {
1664 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1665 err_code |= ERR_ALERT;
1666 goto out;
1667 }
1668
1669 if (*(args[1]))
1670 name = args[1];
1671 else
1672 name = hostname;
1673
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001674 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001675 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001676 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001677 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1678 if (global.server_state_base != NULL) {
1679 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1680 err_code |= ERR_ALERT;
1681 goto out;
1682 }
1683
1684 if (!*(args[1])) {
1685 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1686 err_code |= ERR_FATAL;
1687 goto out;
1688 }
1689
1690 global.server_state_base = strdup(args[1]);
1691 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001692 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1693 if (global.server_state_file != NULL) {
1694 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1695 err_code |= ERR_ALERT;
1696 goto out;
1697 }
1698
1699 if (!*(args[1])) {
1700 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1701 err_code |= ERR_FATAL;
1702 goto out;
1703 }
1704
1705 global.server_state_file = strdup(args[1]);
1706 }
Kevinm48936af2010-12-22 16:08:21 +00001707 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001708 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1709 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001710 if (*(args[1]) == 0) {
1711 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1712 err_code |= ERR_ALERT | ERR_FATAL;
1713 goto out;
1714 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001715 chunk_destroy(&global.log_tag);
1716 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001717 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001718 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001719 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1720 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001721 if (global.spread_checks != 0) {
1722 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001723 err_code |= ERR_ALERT;
1724 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001725 }
1726 if (*(args[1]) == 0) {
1727 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001728 err_code |= ERR_ALERT | ERR_FATAL;
1729 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001730 }
1731 global.spread_checks = atol(args[1]);
1732 if (global.spread_checks < 0 || global.spread_checks > 50) {
1733 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001734 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001735 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001737 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1738 const char *err;
1739 unsigned int val;
1740
William Lallemand1a748ae2015-05-19 16:37:23 +02001741 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1742 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001743 if (*(args[1]) == 0) {
1744 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1745 err_code |= ERR_ALERT | ERR_FATAL;
1746 goto out;
1747 }
1748
1749 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1750 if (err) {
1751 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1752 err_code |= ERR_ALERT | ERR_FATAL;
1753 }
1754 global.max_spread_checks = val;
1755 if (global.max_spread_checks < 0) {
1756 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1757 err_code |= ERR_ALERT | ERR_FATAL;
1758 }
1759 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001760 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1761#ifdef USE_CPU_AFFINITY
1762 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001763 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001764 unsigned long cpus = 0;
1765
1766 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001767 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001768 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001769 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001770 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001771 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001772 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001773 proc = atol(args[1]);
1774 if (proc >= 1 && proc <= LONGBITS)
1775 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001776 }
1777
1778 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001779 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1780 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
1783 }
1784
1785 cur_arg = 2;
1786 while (*args[cur_arg]) {
1787 unsigned int low, high;
1788
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001789 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001790 char *dash = strchr(args[cur_arg], '-');
1791
1792 low = high = str2uic(args[cur_arg]);
1793 if (dash)
1794 high = str2uic(dash + 1);
1795
1796 if (high < low) {
1797 unsigned int swap = low;
1798 low = high;
1799 high = swap;
1800 }
1801
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001802 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001803 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001804 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001805 err_code |= ERR_ALERT | ERR_FATAL;
1806 goto out;
1807 }
1808
1809 while (low <= high)
1810 cpus |= 1UL << low++;
1811 }
1812 else {
1813 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1814 file, linenum, args[0], args[cur_arg]);
1815 err_code |= ERR_ALERT | ERR_FATAL;
1816 goto out;
1817 }
1818 cur_arg++;
1819 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001820 for (i = 0; i < LONGBITS; i++)
1821 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001822 global.cpu_map[i] = cpus;
1823#else
1824 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1825 err_code |= ERR_ALERT | ERR_FATAL;
1826 goto out;
1827#endif
1828 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001829 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1830 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1831 goto out;
1832
1833 if (*(args[2]) == 0) {
1834 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1835 err_code |= ERR_ALERT | ERR_FATAL;
1836 goto out;
1837 }
1838
1839 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1840 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1841 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1842 err_code |= ERR_ALERT | ERR_FATAL;
1843 goto out;
1844 }
1845 }
1846 else if (!strcmp(args[0], "unsetenv")) {
1847 int arg;
1848
1849 if (*(args[1]) == 0) {
1850 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1851 err_code |= ERR_ALERT | ERR_FATAL;
1852 goto out;
1853 }
1854
1855 for (arg = 1; *args[arg]; arg++) {
1856 if (unsetenv(args[arg]) != 0) {
1857 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1858 err_code |= ERR_ALERT | ERR_FATAL;
1859 goto out;
1860 }
1861 }
1862 }
1863 else if (!strcmp(args[0], "resetenv")) {
1864 extern char **environ;
1865 char **env = environ;
1866
1867 /* args contain variable names to keep, one per argument */
1868 while (*env) {
1869 int arg;
1870
1871 /* look for current variable in among all those we want to keep */
1872 for (arg = 1; *args[arg]; arg++) {
1873 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1874 (*env)[strlen(args[arg])] == '=')
1875 break;
1876 }
1877
1878 /* delete this variable */
1879 if (!*args[arg]) {
1880 char *delim = strchr(*env, '=');
1881
1882 if (!delim || delim - *env >= trash.size) {
1883 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1884 err_code |= ERR_ALERT | ERR_FATAL;
1885 goto out;
1886 }
1887
1888 memcpy(trash.str, *env, delim - *env);
1889 trash.str[delim - *env] = 0;
1890
1891 if (unsetenv(trash.str) != 0) {
1892 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1893 err_code |= ERR_ALERT | ERR_FATAL;
1894 goto out;
1895 }
1896 }
1897 else
1898 env++;
1899 }
1900 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001902 struct cfg_kw_list *kwl;
1903 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001904 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001905
1906 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1907 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1908 if (kwl->kw[index].section != CFG_GLOBAL)
1909 continue;
1910 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001911 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001912 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001913 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001914 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001915 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001916 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001917 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001918 err_code |= ERR_WARN;
1919 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001920 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001921 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001922 }
1923 }
1924 }
1925
Willy Tarreaubaaee002006-06-26 02:48:02 +02001926 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001927 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001928 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001929
Willy Tarreau058e9072009-07-20 09:30:05 +02001930 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001931 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001932 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933}
1934
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001935void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001937 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938 defproxy.mode = PR_MODE_TCP;
1939 defproxy.state = PR_STNEW;
1940 defproxy.maxconn = cfg_maxpconn;
1941 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001942 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001943
Simon Horman66183002013-02-23 10:16:43 +09001944 defproxy.defsrv.check.inter = DEF_CHKINTR;
1945 defproxy.defsrv.check.fastinter = 0;
1946 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001947 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1948 defproxy.defsrv.agent.fastinter = 0;
1949 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001950 defproxy.defsrv.check.rise = DEF_RISETIME;
1951 defproxy.defsrv.check.fall = DEF_FALLTIME;
1952 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1953 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001954 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001955 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001956 defproxy.defsrv.maxqueue = 0;
1957 defproxy.defsrv.minconn = 0;
1958 defproxy.defsrv.maxconn = 0;
1959 defproxy.defsrv.slowstart = 0;
1960 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1961 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1962 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001963
1964 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001965 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966}
1967
Willy Tarreauade5ec42010-01-28 19:33:49 +01001968
Willy Tarreau63af98d2014-05-18 08:11:41 +02001969/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1970 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1971 * ERR_FATAL in case of error.
1972 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001973static int create_cond_regex_rule(const char *file, int line,
1974 struct proxy *px, int dir, int action, int flags,
1975 const char *cmd, const char *reg, const char *repl,
1976 const char **cond_start)
1977{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001978 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001979 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001980 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001981 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001982 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001983 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001984 int cs;
1985 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001986
1987 if (px == &defproxy) {
1988 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001989 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001990 goto err;
1991 }
1992
1993 if (*reg == 0) {
1994 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001995 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001996 goto err;
1997 }
1998
1999 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002000 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002001
Willy Tarreau5321c422010-01-28 20:35:13 +01002002 if (cond_start &&
2003 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002004 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
2005 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
2006 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002007 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002008 goto err;
2009 }
2010 }
2011 else if (cond_start && **cond_start) {
2012 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
2013 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002014 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002015 goto err;
2016 }
2017
Willy Tarreau63af98d2014-05-18 08:11:41 +02002018 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002019 (dir == SMP_OPT_DIR_REQ) ?
2020 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
2021 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
2022 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01002023
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002024 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01002025 if (!preg) {
2026 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002027 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002028 goto err;
2029 }
2030
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002031 cs = !(flags & REG_ICASE);
2032 cap = !(flags & REG_NOSUB);
2033 error = NULL;
2034 if (!regex_comp(reg, preg, cs, cap, &error)) {
2035 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
2036 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002037 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002038 goto err;
2039 }
2040
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002041 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01002042 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002043 if (repl && err) {
2044 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
2045 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002046 ret_code |= ERR_ALERT | ERR_FATAL;
2047 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002048 }
2049
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002050 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002051 ret_code |= ERR_WARN;
2052
2053 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002054
Willy Tarreau63af98d2014-05-18 08:11:41 +02002055 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002056 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002057 err:
2058 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002059 free(errmsg);
2060 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002061}
2062
Willy Tarreaubaaee002006-06-26 02:48:02 +02002063/*
William Lallemand51097192015-04-14 16:35:22 +02002064 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02002065 * Returns the error code, 0 if OK, or any combination of :
2066 * - ERR_ABORT: must abort ASAP
2067 * - ERR_FATAL: we can continue parsing but not start the service
2068 * - ERR_WARN: a warning has been emitted
2069 * - ERR_ALERT: an alert has been emitted
2070 * Only the two first ones can stop processing, the two others are just
2071 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002072 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002073int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2074{
2075 static struct peers *curpeers = NULL;
2076 struct peer *newpeer = NULL;
2077 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002078 struct bind_conf *bind_conf;
2079 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002080 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002081 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002082
2083 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002084 if (!*args[1]) {
2085 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002086 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002087 goto out;
2088 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002089
William Lallemand6e62fb62015-04-28 16:55:23 +02002090 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2091 goto out;
2092
Emeric Brun32da3c42010-09-23 18:39:19 +02002093 err = invalid_char(args[1]);
2094 if (err) {
2095 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2096 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002097 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002098 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002099 }
2100
2101 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2102 /*
2103 * If there are two proxies with the same name only following
2104 * combinations are allowed:
2105 */
2106 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002107 Alert("Parsing [%s:%d]: peers section '%s' has the same name as another peers section declared at %s:%d.\n",
Emeric Brun32da3c42010-09-23 18:39:19 +02002108 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002109 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002110 }
2111 }
2112
2113 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
2114 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2115 err_code |= ERR_ALERT | ERR_ABORT;
2116 goto out;
2117 }
2118
2119 curpeers->next = peers;
2120 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002121 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002122 curpeers->conf.line = linenum;
2123 curpeers->last_change = now.tv_sec;
2124 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002125 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002126 }
2127 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002128 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002129 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002130 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002131
2132 if (!*args[2]) {
2133 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2134 file, linenum, args[0]);
2135 err_code |= ERR_ALERT | ERR_FATAL;
2136 goto out;
2137 }
2138
2139 err = invalid_char(args[1]);
2140 if (err) {
2141 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2142 file, linenum, *err, args[1]);
2143 err_code |= ERR_ALERT | ERR_FATAL;
2144 goto out;
2145 }
2146
2147 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2148 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2149 err_code |= ERR_ALERT | ERR_ABORT;
2150 goto out;
2151 }
2152
2153 /* the peers are linked backwards first */
2154 curpeers->count++;
2155 newpeer->next = curpeers->remote;
2156 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002157 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002158 newpeer->conf.line = linenum;
2159
2160 newpeer->last_change = now.tv_sec;
2161 newpeer->id = strdup(args[1]);
2162
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002163 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002164 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002165 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002168 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002169
2170 proto = protocol_by_family(sk->ss_family);
2171 if (!proto || !proto->connect) {
2172 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2173 file, linenum, args[0], args[1]);
2174 err_code |= ERR_ALERT | ERR_FATAL;
2175 goto out;
2176 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002177
2178 if (port1 != port2) {
2179 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2180 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002181 err_code |= ERR_ALERT | ERR_FATAL;
2182 goto out;
2183 }
2184
Willy Tarreau2aa38802013-02-20 19:20:59 +01002185 if (!port1) {
2186 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2187 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002188 err_code |= ERR_ALERT | ERR_FATAL;
2189 goto out;
2190 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002191
Emeric Brun32da3c42010-09-23 18:39:19 +02002192 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002193 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002194 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002195 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002196
Emeric Brun32da3c42010-09-23 18:39:19 +02002197 if (strcmp(newpeer->id, localpeer) == 0) {
2198 /* Current is local peer, it define a frontend */
2199 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002200 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002201
2202 if (!curpeers->peers_fe) {
2203 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2204 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2205 err_code |= ERR_ALERT | ERR_ABORT;
2206 goto out;
2207 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002208
Willy Tarreau237250c2011-07-29 01:49:03 +02002209 init_new_proxy(curpeers->peers_fe);
2210 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002211 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002212 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2213 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002214 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002215
2216 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2217
Willy Tarreau902636f2013-03-10 19:44:48 +01002218 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2219 if (errmsg && *errmsg) {
2220 indent_msg(&errmsg, 2);
2221 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002222 }
2223 else
2224 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2225 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002226 err_code |= ERR_FATAL;
2227 goto out;
2228 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002229
2230 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002231 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002232 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2233 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002234 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002235 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002236 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002237 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002238 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2239 global.maxsock += l->maxconn;
2240 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002241 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002242 else {
2243 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2244 file, linenum, args[0], args[1],
2245 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2246 err_code |= ERR_FATAL;
2247 goto out;
2248 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002249 }
2250 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002251 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2252 curpeers->state = PR_STSTOPPED;
2253 }
2254 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2255 curpeers->state = PR_STNEW;
2256 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002257 else if (*args[0] != 0) {
2258 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
2261 }
2262
2263out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002264 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002265 return err_code;
2266}
2267
Baptiste Assmann325137d2015-04-13 23:40:55 +02002268/*
2269 * Parse a <resolvers> section.
2270 * Returns the error code, 0 if OK, or any combination of :
2271 * - ERR_ABORT: must abort ASAP
2272 * - ERR_FATAL: we can continue parsing but not start the service
2273 * - ERR_WARN: a warning has been emitted
2274 * - ERR_ALERT: an alert has been emitted
2275 * Only the two first ones can stop processing, the two others are just
2276 * indicators.
2277 */
2278int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2279{
2280 static struct dns_resolvers *curr_resolvers = NULL;
2281 struct dns_nameserver *newnameserver = NULL;
2282 const char *err;
2283 int err_code = 0;
2284 char *errmsg = NULL;
2285
2286 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2287 if (!*args[1]) {
2288 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2289 err_code |= ERR_ALERT | ERR_ABORT;
2290 goto out;
2291 }
2292
2293 err = invalid_char(args[1]);
2294 if (err) {
2295 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2296 file, linenum, *err, args[0], args[1]);
2297 err_code |= ERR_ALERT | ERR_ABORT;
2298 goto out;
2299 }
2300
2301 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2302 /* Error if two resolvers owns the same name */
2303 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2304 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2305 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2306 err_code |= ERR_ALERT | ERR_ABORT;
2307 }
2308 }
2309
2310 if ((curr_resolvers = (struct dns_resolvers *)calloc(1, sizeof(struct dns_resolvers))) == NULL) {
2311 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2312 err_code |= ERR_ALERT | ERR_ABORT;
2313 goto out;
2314 }
2315
2316 /* default values */
2317 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2318 curr_resolvers->conf.file = strdup(file);
2319 curr_resolvers->conf.line = linenum;
2320 curr_resolvers->id = strdup(args[1]);
2321 curr_resolvers->query_ids = EB_ROOT;
2322 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002323 curr_resolvers->hold.valid = 10000;
2324 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002325 curr_resolvers->resolve_retries = 3;
2326 LIST_INIT(&curr_resolvers->nameserver_list);
2327 LIST_INIT(&curr_resolvers->curr_resolution);
2328 }
2329 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2330 struct sockaddr_storage *sk;
2331 int port1, port2;
2332 struct protocol *proto;
2333
2334 if (!*args[2]) {
2335 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2336 file, linenum, args[0]);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340
2341 err = invalid_char(args[1]);
2342 if (err) {
2343 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2344 file, linenum, *err, args[1]);
2345 err_code |= ERR_ALERT | ERR_FATAL;
2346 goto out;
2347 }
2348
Baptiste Assmanna315c552015-11-02 22:55:49 +01002349 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2350 /* Error if two resolvers owns the same name */
2351 if (strcmp(newnameserver->id, args[1]) == 0) {
2352 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2353 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2354 err_code |= ERR_ALERT | ERR_FATAL;
2355 }
2356 }
2357
Baptiste Assmann325137d2015-04-13 23:40:55 +02002358 if ((newnameserver = (struct dns_nameserver *)calloc(1, sizeof(struct dns_nameserver))) == NULL) {
2359 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2360 err_code |= ERR_ALERT | ERR_ABORT;
2361 goto out;
2362 }
2363
2364 /* the nameservers are linked backward first */
2365 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2366 curr_resolvers->count_nameservers++;
2367 newnameserver->resolvers = curr_resolvers;
2368 newnameserver->conf.file = strdup(file);
2369 newnameserver->conf.line = linenum;
2370 newnameserver->id = strdup(args[1]);
2371
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002372 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002373 if (!sk) {
2374 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
2377 }
2378
2379 proto = protocol_by_family(sk->ss_family);
2380 if (!proto || !proto->connect) {
2381 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2382 file, linenum, args[0], args[1]);
2383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
2385 }
2386
2387 if (port1 != port2) {
2388 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2389 file, linenum, args[0], args[1], args[2]);
2390 err_code |= ERR_ALERT | ERR_FATAL;
2391 goto out;
2392 }
2393
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002394 if (!port1 && !port2) {
2395 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2396 file, linenum, args[0], args[1]);
2397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
2399 }
2400
Baptiste Assmann325137d2015-04-13 23:40:55 +02002401 newnameserver->addr = *sk;
2402 }
2403 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2404 const char *res;
2405 unsigned int time;
2406
2407 if (!*args[2]) {
2408 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2409 file, linenum, args[0]);
2410 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
2413 }
2414 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2415 if (res) {
2416 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2417 file, linenum, *res, args[0]);
2418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
2420 }
2421 if (strcmp(args[1], "valid") == 0)
2422 curr_resolvers->hold.valid = time;
2423 else {
2424 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2425 file, linenum, args[0], args[1]);
2426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
2428 }
2429
2430 }
2431 else if (strcmp(args[0], "resolve_retries") == 0) {
2432 if (!*args[1]) {
2433 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2434 file, linenum, args[0]);
2435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
2437 }
2438 curr_resolvers->resolve_retries = atoi(args[1]);
2439 }
2440 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002441 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002442 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2443 file, linenum, args[0]);
2444 err_code |= ERR_ALERT | ERR_FATAL;
2445 goto out;
2446 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002447 else if (strcmp(args[1], "retry") == 0) {
2448 const char *res;
2449 unsigned int timeout_retry;
2450
2451 if (!*args[2]) {
2452 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2453 file, linenum, args[0], args[1]);
2454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
2456 }
2457 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2458 if (res) {
2459 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2460 file, linenum, *res, args[0], args[1]);
2461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
2463 }
2464 curr_resolvers->timeout.retry = timeout_retry;
2465 }
2466 else {
2467 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2468 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
2471 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002472 } /* neither "nameserver" nor "resolvers" */
2473 else if (*args[0] != 0) {
2474 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
2477 }
2478
2479 out:
2480 free(errmsg);
2481 return err_code;
2482}
Simon Horman0d16a402015-01-30 11:22:58 +09002483
2484/*
William Lallemand51097192015-04-14 16:35:22 +02002485 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002486 * Returns the error code, 0 if OK, or any combination of :
2487 * - ERR_ABORT: must abort ASAP
2488 * - ERR_FATAL: we can continue parsing but not start the service
2489 * - ERR_WARN: a warning has been emitted
2490 * - ERR_ALERT: an alert has been emitted
2491 * Only the two first ones can stop processing, the two others are just
2492 * indicators.
2493 */
2494int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2495{
2496 static struct mailers *curmailers = NULL;
2497 struct mailer *newmailer = NULL;
2498 const char *err;
2499 int err_code = 0;
2500 char *errmsg = NULL;
2501
2502 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2503 if (!*args[1]) {
2504 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2505 err_code |= ERR_ALERT | ERR_ABORT;
2506 goto out;
2507 }
2508
2509 err = invalid_char(args[1]);
2510 if (err) {
2511 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2512 file, linenum, *err, args[0], args[1]);
2513 err_code |= ERR_ALERT | ERR_ABORT;
2514 goto out;
2515 }
2516
2517 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2518 /*
2519 * If there are two proxies with the same name only following
2520 * combinations are allowed:
2521 */
2522 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002523 Alert("Parsing [%s:%d]: mailers section '%s' has the same name as another mailers section declared at %s:%d.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002524 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002525 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002526 }
2527 }
2528
2529 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2530 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2531 err_code |= ERR_ALERT | ERR_ABORT;
2532 goto out;
2533 }
2534
2535 curmailers->next = mailers;
2536 mailers = curmailers;
2537 curmailers->conf.file = strdup(file);
2538 curmailers->conf.line = linenum;
2539 curmailers->id = strdup(args[1]);
2540 }
2541 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2542 struct sockaddr_storage *sk;
2543 int port1, port2;
2544 struct protocol *proto;
2545
2546 if (!*args[2]) {
2547 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2548 file, linenum, args[0]);
2549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
2551 }
2552
2553 err = invalid_char(args[1]);
2554 if (err) {
2555 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2556 file, linenum, *err, args[1]);
2557 err_code |= ERR_ALERT | ERR_FATAL;
2558 goto out;
2559 }
2560
2561 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2562 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2563 err_code |= ERR_ALERT | ERR_ABORT;
2564 goto out;
2565 }
2566
2567 /* the mailers are linked backwards first */
2568 curmailers->count++;
2569 newmailer->next = curmailers->mailer_list;
2570 curmailers->mailer_list = newmailer;
2571 newmailer->mailers = curmailers;
2572 newmailer->conf.file = strdup(file);
2573 newmailer->conf.line = linenum;
2574
2575 newmailer->id = strdup(args[1]);
2576
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002577 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002578 if (!sk) {
2579 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2580 err_code |= ERR_ALERT | ERR_FATAL;
2581 goto out;
2582 }
2583
2584 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002585 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2586 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002587 file, linenum, args[0], args[1]);
2588 err_code |= ERR_ALERT | ERR_FATAL;
2589 goto out;
2590 }
2591
2592 if (port1 != port2) {
2593 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2594 file, linenum, args[0], args[1], args[2]);
2595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
2597 }
2598
2599 if (!port1) {
2600 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2601 file, linenum, args[0], args[1], args[2]);
2602 err_code |= ERR_ALERT | ERR_FATAL;
2603 goto out;
2604 }
2605
2606 newmailer->addr = *sk;
2607 newmailer->proto = proto;
2608 newmailer->xprt = &raw_sock;
2609 newmailer->sock_init_arg = NULL;
2610 } /* neither "mailer" nor "mailers" */
2611 else if (*args[0] != 0) {
2612 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2613 err_code |= ERR_ALERT | ERR_FATAL;
2614 goto out;
2615 }
2616
2617out:
2618 free(errmsg);
2619 return err_code;
2620}
2621
Simon Horman9dc49962015-01-30 11:22:59 +09002622static void free_email_alert(struct proxy *p)
2623{
2624 free(p->email_alert.mailers.name);
2625 p->email_alert.mailers.name = NULL;
2626 free(p->email_alert.from);
2627 p->email_alert.from = NULL;
2628 free(p->email_alert.to);
2629 p->email_alert.to = NULL;
2630 free(p->email_alert.myhostname);
2631 p->email_alert.myhostname = NULL;
2632}
2633
Willy Tarreau3842f002009-06-14 11:39:52 +02002634int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002635{
2636 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002637 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002638 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002639 int rc;
2640 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002641 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002642 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002643 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002644 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002645 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002646
Willy Tarreau977b8e42006-12-29 14:19:17 +01002647 if (!strcmp(args[0], "listen"))
2648 rc = PR_CAP_LISTEN;
2649 else if (!strcmp(args[0], "frontend"))
2650 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002651 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002652 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002653 else
2654 rc = PR_CAP_NONE;
2655
2656 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002657 if (!*args[1]) {
2658 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2659 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2660 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002661 err_code |= ERR_ALERT | ERR_ABORT;
2662 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002663 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002664
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002665 err = invalid_char(args[1]);
2666 if (err) {
2667 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2668 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002669 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002670 }
2671
Willy Tarreau8f50b682015-05-26 11:45:02 +02002672 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2673 if (curproxy) {
2674 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2675 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2676 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002677 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002678 }
2679
Willy Tarreaubaaee002006-06-26 02:48:02 +02002680 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2681 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002682 err_code |= ERR_ALERT | ERR_ABORT;
2683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002685
Willy Tarreau97cb7802010-01-03 20:23:58 +01002686 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687 curproxy->next = proxy;
2688 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002689 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2690 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002691 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002693 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002694 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002695
William Lallemand6e62fb62015-04-28 16:55:23 +02002696 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2697 if (curproxy->cap & PR_CAP_FE)
2698 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2699 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 }
2701
2702 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002703 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002704 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002705
Willy Tarreaubaaee002006-06-26 02:48:02 +02002706 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002707 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002708 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002709 curproxy->no_options = defproxy.no_options;
2710 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002711 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002712 curproxy->except_net = defproxy.except_net;
2713 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002714 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002715 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002716
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002717 if (defproxy.fwdfor_hdr_len) {
2718 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2719 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2720 }
2721
Willy Tarreaub86db342009-11-30 11:50:16 +01002722 if (defproxy.orgto_hdr_len) {
2723 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2724 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2725 }
2726
Mark Lamourinec2247f02012-01-04 13:02:01 -05002727 if (defproxy.server_id_hdr_len) {
2728 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2729 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2730 }
2731
Willy Tarreau977b8e42006-12-29 14:19:17 +01002732 if (curproxy->cap & PR_CAP_FE) {
2733 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002734 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002735 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002736
2737 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002738 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2739 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002740
2741 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2742 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002743
Willy Tarreau977b8e42006-12-29 14:19:17 +01002744 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002745 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002746 curproxy->fullconn = defproxy.fullconn;
2747 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002748 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002749 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002750
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002751 if (defproxy.check_req) {
2752 curproxy->check_req = calloc(1, defproxy.check_len);
2753 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2754 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002755 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002757 if (defproxy.expect_str) {
2758 curproxy->expect_str = strdup(defproxy.expect_str);
2759 if (defproxy.expect_regex) {
2760 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002761 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2762 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002763 }
2764 }
2765
Willy Tarreau67402132012-05-31 20:40:20 +02002766 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002767 if (defproxy.cookie_name)
2768 curproxy->cookie_name = strdup(defproxy.cookie_name);
2769 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002770 if (defproxy.cookie_domain)
2771 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002772
Willy Tarreau31936852010-10-06 16:59:56 +02002773 if (defproxy.cookie_maxidle)
2774 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2775
2776 if (defproxy.cookie_maxlife)
2777 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2778
Emeric Brun647caf12009-06-30 17:57:00 +02002779 if (defproxy.rdp_cookie_name)
2780 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2781 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2782
Willy Tarreau01732802007-11-01 22:48:15 +01002783 if (defproxy.url_param_name)
2784 curproxy->url_param_name = strdup(defproxy.url_param_name);
2785 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002786
Benoitaffb4812009-03-25 13:02:10 +01002787 if (defproxy.hh_name)
2788 curproxy->hh_name = strdup(defproxy.hh_name);
2789 curproxy->hh_len = defproxy.hh_len;
2790 curproxy->hh_match_domain = defproxy.hh_match_domain;
2791
Willy Tarreauef9a3602012-12-08 22:29:20 +01002792 if (defproxy.conn_src.iface_name)
2793 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2794 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002795 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002796#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002797 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002798#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002799 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002800 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002801
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002802 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002803 if (defproxy.capture_name)
2804 curproxy->capture_name = strdup(defproxy.capture_name);
2805 curproxy->capture_namelen = defproxy.capture_namelen;
2806 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002807 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002808
Willy Tarreau977b8e42006-12-29 14:19:17 +01002809 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002810 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002811 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002812 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002813 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002814 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002815 curproxy->mon_net = defproxy.mon_net;
2816 curproxy->mon_mask = defproxy.mon_mask;
2817 if (defproxy.monitor_uri)
2818 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2819 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002820 if (defproxy.defbe.name)
2821 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002822
2823 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002824 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2825 if (curproxy->conf.logformat_string &&
2826 curproxy->conf.logformat_string != default_http_log_format &&
2827 curproxy->conf.logformat_string != default_tcp_log_format &&
2828 curproxy->conf.logformat_string != clf_http_log_format)
2829 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2830
2831 if (defproxy.conf.lfs_file) {
2832 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2833 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2834 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002835
2836 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2837 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2838 if (curproxy->conf.logformat_sd_string &&
2839 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2840 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2841
2842 if (defproxy.conf.lfsd_file) {
2843 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2844 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2845 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002846 }
2847
2848 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002849 curproxy->timeout.connect = defproxy.timeout.connect;
2850 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002851 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002852 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002853 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002854 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002855 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002856 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002857 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002858 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002859 }
2860
Willy Tarreaubaaee002006-06-26 02:48:02 +02002861 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002862 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002863
2864 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002865 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002866 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002867 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002868 LIST_INIT(&node->list);
2869 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2870 }
2871
Willy Tarreau62a61232013-04-12 18:13:46 +02002872 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2873 if (curproxy->conf.uniqueid_format_string)
2874 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2875
Dragan Dosen43885c72015-10-01 13:18:13 +02002876 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002877
Willy Tarreau62a61232013-04-12 18:13:46 +02002878 if (defproxy.conf.uif_file) {
2879 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2880 curproxy->conf.uif_line = defproxy.conf.uif_line;
2881 }
William Lallemanda73203e2012-03-12 12:48:57 +01002882
2883 /* copy default header unique id */
2884 if (defproxy.header_unique_id)
2885 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2886
William Lallemand82fe75c2012-10-23 10:25:10 +02002887 /* default compression options */
2888 if (defproxy.comp != NULL) {
2889 curproxy->comp = calloc(1, sizeof(struct comp));
2890 curproxy->comp->algos = defproxy.comp->algos;
2891 curproxy->comp->types = defproxy.comp->types;
2892 }
2893
Willy Tarreaubaaee002006-06-26 02:48:02 +02002894 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002895 curproxy->conf.used_listener_id = EB_ROOT;
2896 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002897
Simon Horman98637e52014-06-20 12:30:16 +09002898 if (defproxy.check_path)
2899 curproxy->check_path = strdup(defproxy.check_path);
2900 if (defproxy.check_command)
2901 curproxy->check_command = strdup(defproxy.check_command);
2902
Simon Horman9dc49962015-01-30 11:22:59 +09002903 if (defproxy.email_alert.mailers.name)
2904 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2905 if (defproxy.email_alert.from)
2906 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2907 if (defproxy.email_alert.to)
2908 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2909 if (defproxy.email_alert.myhostname)
2910 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002911 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002912 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002913
Willy Tarreau93893792009-07-23 13:19:11 +02002914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 }
2916 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2917 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002918 /* FIXME-20070101: we should do this too at the end of the
2919 * config parsing to free all default values.
2920 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002921 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2922 err_code |= ERR_ABORT;
2923 goto out;
2924 }
2925
Willy Tarreaua534fea2008-08-03 12:19:50 +02002926 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002927 free(defproxy.check_command);
2928 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002929 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002930 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002931 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002932 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002933 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002934 free(defproxy.capture_name);
2935 free(defproxy.monitor_uri);
2936 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002937 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002938 free(defproxy.fwdfor_hdr_name);
2939 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002940 free(defproxy.orgto_hdr_name);
2941 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002942 free(defproxy.server_id_hdr_name);
2943 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002944 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002945 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002946 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002947 free(defproxy.expect_regex);
2948 defproxy.expect_regex = NULL;
2949 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002950
Willy Tarreau62a61232013-04-12 18:13:46 +02002951 if (defproxy.conf.logformat_string != default_http_log_format &&
2952 defproxy.conf.logformat_string != default_tcp_log_format &&
2953 defproxy.conf.logformat_string != clf_http_log_format)
2954 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002955
Willy Tarreau62a61232013-04-12 18:13:46 +02002956 free(defproxy.conf.uniqueid_format_string);
2957 free(defproxy.conf.lfs_file);
2958 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002959 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002960 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002961
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002962 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2963 free(defproxy.conf.logformat_sd_string);
2964 free(defproxy.conf.lfsd_file);
2965
Willy Tarreaua534fea2008-08-03 12:19:50 +02002966 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002967 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002968
Willy Tarreaubaaee002006-06-26 02:48:02 +02002969 /* we cannot free uri_auth because it might already be used */
2970 init_default_instance();
2971 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002972 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2973 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002974 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002976 }
2977 else if (curproxy == NULL) {
2978 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002981 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002982
2983 /* update the current file and line being parsed */
2984 curproxy->conf.args.file = curproxy->conf.file;
2985 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002986
2987 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002988 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2989 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2990 if (err_code & ERR_FATAL)
2991 goto out;
2992 }
2993 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002994 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002995 int cur_arg;
2996
Willy Tarreaubaaee002006-06-26 02:48:02 +02002997 if (curproxy == &defproxy) {
2998 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002999 err_code |= ERR_ALERT | ERR_FATAL;
3000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003001 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003002 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003003 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003004
Willy Tarreau24709282013-03-10 21:32:12 +01003005 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003006 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003007 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003008 err_code |= ERR_ALERT | ERR_FATAL;
3009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003011
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003012 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003013
3014 /* use default settings for unix sockets */
3015 bind_conf->ux.uid = global.unix_bind.ux.uid;
3016 bind_conf->ux.gid = global.unix_bind.ux.gid;
3017 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003018
3019 /* NOTE: the following line might create several listeners if there
3020 * are comma-separated IPs or port ranges. So all further processing
3021 * will have to be applied to all listeners created after last_listen.
3022 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003023 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3024 if (errmsg && *errmsg) {
3025 indent_msg(&errmsg, 2);
3026 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003027 }
3028 else
3029 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3030 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003031 err_code |= ERR_ALERT | ERR_FATAL;
3032 goto out;
3033 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003034
Willy Tarreau4348fad2012-09-20 16:48:07 +02003035 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3036 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003037 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003038 }
3039
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003040 cur_arg = 2;
3041 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003042 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003043 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003044 char *err;
3045
Willy Tarreau26982662012-09-12 23:17:10 +02003046 kw = bind_find_kw(args[cur_arg]);
3047 if (kw) {
3048 char *err = NULL;
3049 int code;
3050
3051 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003052 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3053 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003054 cur_arg += 1 + kw->skip ;
3055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
3057 }
3058
Willy Tarreau4348fad2012-09-20 16:48:07 +02003059 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003060 err_code |= code;
3061
3062 if (code) {
3063 if (err && *err) {
3064 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003065 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003066 }
3067 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003068 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3069 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003070 if (code & ERR_FATAL) {
3071 free(err);
3072 cur_arg += 1 + kw->skip;
3073 goto out;
3074 }
3075 }
3076 free(err);
3077 cur_arg += 1 + kw->skip;
3078 continue;
3079 }
3080
Willy Tarreau8638f482012-09-18 18:01:17 +02003081 err = NULL;
3082 if (!bind_dumped) {
3083 bind_dump_kws(&err);
3084 indent_msg(&err, 4);
3085 bind_dumped = 1;
3086 }
3087
3088 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3089 file, linenum, args[0], args[1], args[cur_arg],
3090 err ? " Registered keywords :" : "", err ? err : "");
3091 free(err);
3092
Willy Tarreau93893792009-07-23 13:19:11 +02003093 err_code |= ERR_ALERT | ERR_FATAL;
3094 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003095 }
Willy Tarreau93893792009-07-23 13:19:11 +02003096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003097 }
3098 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003099 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003100 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3101 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003102 err_code |= ERR_ALERT | ERR_FATAL;
3103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003104 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003105 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003106 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003107
Willy Tarreaubaaee002006-06-26 02:48:02 +02003108 /* flush useless bits */
3109 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003111 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003112 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003113 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003114 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003115
William Lallemanddf1425a2015-04-28 20:17:49 +02003116 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3117 goto out;
3118
Willy Tarreau1c47f852006-07-09 08:22:27 +02003119 if (!*args[1]) {
3120 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3121 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003122 err_code |= ERR_ALERT | ERR_FATAL;
3123 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003124 }
3125
Willy Tarreaua534fea2008-08-03 12:19:50 +02003126 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003127 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003128 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003129 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003130 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3131
Willy Tarreau93893792009-07-23 13:19:11 +02003132 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003133 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003134 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003135 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3136 goto out;
3137
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3139 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3140 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3141 else {
3142 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003143 err_code |= ERR_ALERT | ERR_FATAL;
3144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145 }
3146 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003147 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003148 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003149
3150 if (curproxy == &defproxy) {
3151 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3152 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003155 }
3156
William Lallemanddf1425a2015-04-28 20:17:49 +02003157 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3158 goto out;
3159
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003160 if (!*args[1]) {
3161 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3162 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003165 }
3166
3167 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003168 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003169 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003170
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003171 if (curproxy->uuid <= 0) {
3172 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003173 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003176 }
3177
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003178 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3179 if (node) {
3180 struct proxy *target = container_of(node, struct proxy, conf.id);
3181 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3182 file, linenum, proxy_type_str(curproxy), curproxy->id,
3183 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
3186 }
3187 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003188 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003189 else if (!strcmp(args[0], "description")) {
3190 int i, len=0;
3191 char *d;
3192
Cyril Bonté99ed3272010-01-24 23:29:44 +01003193 if (curproxy == &defproxy) {
3194 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3195 file, linenum, args[0]);
3196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
3198 }
3199
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003200 if (!*args[1]) {
3201 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3202 file, linenum, args[0]);
3203 return -1;
3204 }
3205
Willy Tarreau348acfe2014-04-14 15:00:39 +02003206 for (i = 1; *args[i]; i++)
3207 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003208
3209 d = (char *)calloc(1, len);
3210 curproxy->desc = d;
3211
Willy Tarreau348acfe2014-04-14 15:00:39 +02003212 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3213 for (i = 2; *args[i]; i++)
3214 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003215
3216 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003218 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3219 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003220 curproxy->state = PR_STSTOPPED;
3221 }
3222 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003223 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003225 curproxy->state = PR_STNEW;
3226 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003227 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3228 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003229 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003230
3231 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003232 unsigned int low, high;
3233
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003234 if (strcmp(args[cur_arg], "all") == 0) {
3235 set = 0;
3236 break;
3237 }
3238 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003239 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003240 }
3241 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003242 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003243 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003244 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003245 char *dash = strchr(args[cur_arg], '-');
3246
3247 low = high = str2uic(args[cur_arg]);
3248 if (dash)
3249 high = str2uic(dash + 1);
3250
3251 if (high < low) {
3252 unsigned int swap = low;
3253 low = high;
3254 high = swap;
3255 }
3256
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003257 if (low < 1 || high > LONGBITS) {
3258 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3259 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003260 err_code |= ERR_ALERT | ERR_FATAL;
3261 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003262 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003263 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003264 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003265 }
3266 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003267 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3268 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003269 err_code |= ERR_ALERT | ERR_FATAL;
3270 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003271 }
3272 cur_arg++;
3273 }
3274 curproxy->bind_proc = set;
3275 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003276 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003277 if (curproxy == &defproxy) {
3278 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003279 err_code |= ERR_ALERT | ERR_FATAL;
3280 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003281 }
3282
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003283 err = invalid_char(args[1]);
3284 if (err) {
3285 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3286 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003287 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003288 }
3289
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003290 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003291 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3292 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003293 err_code |= ERR_ALERT | ERR_FATAL;
3294 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003295 }
3296 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003297 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3298 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003299
Willy Tarreau977b8e42006-12-29 14:19:17 +01003300 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003301 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003302
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 if (*(args[1]) == 0) {
3304 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3305 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003306 err_code |= ERR_ALERT | ERR_FATAL;
3307 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003309
Willy Tarreau67402132012-05-31 20:40:20 +02003310 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003311 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003312 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003313 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003314 curproxy->cookie_name = strdup(args[1]);
3315 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003316
Willy Tarreaubaaee002006-06-26 02:48:02 +02003317 cur_arg = 2;
3318 while (*(args[cur_arg])) {
3319 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003320 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003321 }
3322 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003323 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 }
3325 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003326 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003327 }
3328 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003329 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 }
3331 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003332 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003334 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003335 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003336 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003338 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003339 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003340 else if (!strcmp(args[cur_arg], "httponly")) {
3341 curproxy->ck_opts |= PR_CK_HTTPONLY;
3342 }
3343 else if (!strcmp(args[cur_arg], "secure")) {
3344 curproxy->ck_opts |= PR_CK_SECURE;
3345 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003346 else if (!strcmp(args[cur_arg], "domain")) {
3347 if (!*args[cur_arg + 1]) {
3348 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3349 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003352 }
3353
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003354 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003355 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003356 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3357 " dots nor does not start with a dot."
3358 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003359 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003360 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003361 }
3362
3363 err = invalid_domainchar(args[cur_arg + 1]);
3364 if (err) {
3365 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3366 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003367 err_code |= ERR_ALERT | ERR_FATAL;
3368 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003369 }
3370
Willy Tarreau68a897b2009-12-03 23:28:34 +01003371 if (!curproxy->cookie_domain) {
3372 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3373 } else {
3374 /* one domain was already specified, add another one by
3375 * building the string which will be returned along with
3376 * the cookie.
3377 */
3378 char *new_ptr;
3379 int new_len = strlen(curproxy->cookie_domain) +
3380 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3381 new_ptr = malloc(new_len);
3382 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3383 free(curproxy->cookie_domain);
3384 curproxy->cookie_domain = new_ptr;
3385 }
Willy Tarreau31936852010-10-06 16:59:56 +02003386 cur_arg++;
3387 }
3388 else if (!strcmp(args[cur_arg], "maxidle")) {
3389 unsigned int maxidle;
3390 const char *res;
3391
3392 if (!*args[cur_arg + 1]) {
3393 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3394 file, linenum, args[cur_arg]);
3395 err_code |= ERR_ALERT | ERR_FATAL;
3396 goto out;
3397 }
3398
3399 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3400 if (res) {
3401 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3402 file, linenum, *res, args[cur_arg]);
3403 err_code |= ERR_ALERT | ERR_FATAL;
3404 goto out;
3405 }
3406 curproxy->cookie_maxidle = maxidle;
3407 cur_arg++;
3408 }
3409 else if (!strcmp(args[cur_arg], "maxlife")) {
3410 unsigned int maxlife;
3411 const char *res;
3412
3413 if (!*args[cur_arg + 1]) {
3414 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3415 file, linenum, args[cur_arg]);
3416 err_code |= ERR_ALERT | ERR_FATAL;
3417 goto out;
3418 }
3419
3420 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3421 if (res) {
3422 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3423 file, linenum, *res, args[cur_arg]);
3424 err_code |= ERR_ALERT | ERR_FATAL;
3425 goto out;
3426 }
3427 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003428 cur_arg++;
3429 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003430 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003431 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 +02003432 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003433 err_code |= ERR_ALERT | ERR_FATAL;
3434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003435 }
3436 cur_arg++;
3437 }
Willy Tarreau67402132012-05-31 20:40:20 +02003438 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003439 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3440 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003441 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003442 }
3443
Willy Tarreau67402132012-05-31 20:40:20 +02003444 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003445 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3446 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003447 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003448 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003449
Willy Tarreau67402132012-05-31 20:40:20 +02003450 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003451 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3452 file, linenum);
3453 err_code |= ERR_ALERT | ERR_FATAL;
3454 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003455 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003456 else if (!strcmp(args[0], "email-alert")) {
3457 if (*(args[1]) == 0) {
3458 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3459 file, linenum, args[0]);
3460 err_code |= ERR_ALERT | ERR_FATAL;
3461 goto out;
3462 }
3463
3464 if (!strcmp(args[1], "from")) {
3465 if (*(args[1]) == 0) {
3466 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3467 file, linenum, args[1]);
3468 err_code |= ERR_ALERT | ERR_FATAL;
3469 goto out;
3470 }
3471 free(curproxy->email_alert.from);
3472 curproxy->email_alert.from = strdup(args[2]);
3473 }
3474 else if (!strcmp(args[1], "mailers")) {
3475 if (*(args[1]) == 0) {
3476 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3477 file, linenum, args[1]);
3478 err_code |= ERR_ALERT | ERR_FATAL;
3479 goto out;
3480 }
3481 free(curproxy->email_alert.mailers.name);
3482 curproxy->email_alert.mailers.name = strdup(args[2]);
3483 }
3484 else if (!strcmp(args[1], "myhostname")) {
3485 if (*(args[1]) == 0) {
3486 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3487 file, linenum, args[1]);
3488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
3490 }
3491 free(curproxy->email_alert.myhostname);
3492 curproxy->email_alert.myhostname = strdup(args[2]);
3493 }
Simon Horman64e34162015-02-06 11:11:57 +09003494 else if (!strcmp(args[1], "level")) {
3495 curproxy->email_alert.level = get_log_level(args[2]);
3496 if (curproxy->email_alert.level < 0) {
3497 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3498 file, linenum, args[1], args[2]);
3499 err_code |= ERR_ALERT | ERR_FATAL;
3500 goto out;
3501 }
3502 }
Simon Horman9dc49962015-01-30 11:22:59 +09003503 else if (!strcmp(args[1], "to")) {
3504 if (*(args[1]) == 0) {
3505 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3506 file, linenum, args[1]);
3507 err_code |= ERR_ALERT | ERR_FATAL;
3508 goto out;
3509 }
3510 free(curproxy->email_alert.to);
3511 curproxy->email_alert.to = strdup(args[2]);
3512 }
3513 else {
3514 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3515 file, linenum, args[1]);
3516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
3518 }
Simon Horman64e34162015-02-06 11:11:57 +09003519 /* Indicate that the email_alert is at least partially configured */
3520 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003521 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003522 else if (!strcmp(args[0], "external-check")) {
3523 if (*(args[1]) == 0) {
3524 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3525 file, linenum, args[0]);
3526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
3528 }
3529
3530 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003531 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003532 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003533 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003534 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->check_command);
3540 curproxy->check_command = strdup(args[2]);
3541 }
3542 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003543 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003544 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003545 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003546 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3547 file, linenum, args[1]);
3548 err_code |= ERR_ALERT | ERR_FATAL;
3549 goto out;
3550 }
3551 free(curproxy->check_path);
3552 curproxy->check_path = strdup(args[2]);
3553 }
3554 else {
3555 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3556 file, linenum, args[1]);
3557 err_code |= ERR_ALERT | ERR_FATAL;
3558 goto out;
3559 }
3560 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003561 else if (!strcmp(args[0], "persist")) { /* persist */
3562 if (*(args[1]) == 0) {
3563 Alert("parsing [%s:%d] : missing persist method.\n",
3564 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003565 err_code |= ERR_ALERT | ERR_FATAL;
3566 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003567 }
3568
3569 if (!strncmp(args[1], "rdp-cookie", 10)) {
3570 curproxy->options2 |= PR_O2_RDPC_PRST;
3571
Emeric Brunb982a3d2010-01-04 15:45:53 +01003572 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003573 const char *beg, *end;
3574
3575 beg = args[1] + 11;
3576 end = strchr(beg, ')');
3577
William Lallemanddf1425a2015-04-28 20:17:49 +02003578 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3579 goto out;
3580
Emeric Brun647caf12009-06-30 17:57:00 +02003581 if (!end || end == beg) {
3582 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3583 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003584 err_code |= ERR_ALERT | ERR_FATAL;
3585 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003586 }
3587
3588 free(curproxy->rdp_cookie_name);
3589 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3590 curproxy->rdp_cookie_len = end-beg;
3591 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003592 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003593 free(curproxy->rdp_cookie_name);
3594 curproxy->rdp_cookie_name = strdup("msts");
3595 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3596 }
3597 else { /* syntax */
3598 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3599 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003600 err_code |= ERR_ALERT | ERR_FATAL;
3601 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003602 }
3603 }
3604 else {
3605 Alert("parsing [%s:%d] : unknown persist method.\n",
3606 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003607 err_code |= ERR_ALERT | ERR_FATAL;
3608 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003609 }
3610 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003611 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003612 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
3615 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003616 else if (!strcmp(args[0], "load-server-state-from-file")) {
3617 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3618 err_code |= ERR_WARN;
3619 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3620 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3621 }
3622 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3623 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3624 }
3625 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3626 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3627 }
3628 else {
3629 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3630 file, linenum, args[0], args[1]);
3631 err_code |= ERR_ALERT | ERR_FATAL;
3632 goto out;
3633 }
3634 }
3635 else if (!strcmp(args[0], "server-state-file-name")) {
3636 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3637 err_code |= ERR_WARN;
3638 if (*(args[1]) == 0) {
3639 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3640 file, linenum, args[0]);
3641 err_code |= ERR_ALERT | ERR_FATAL;
3642 goto out;
3643 }
3644 else if (!strcmp(args[1], "use-backend-name"))
3645 curproxy->server_state_file_name = strdup(curproxy->id);
3646 else
3647 curproxy->server_state_file_name = strdup(args[1]);
3648 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003649 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003650 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003651 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003652
Willy Tarreaubaaee002006-06-26 02:48:02 +02003653 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003654 if (curproxy == &defproxy) {
3655 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3656 err_code |= ERR_ALERT | ERR_FATAL;
3657 goto out;
3658 }
3659
William Lallemand1a748ae2015-05-19 16:37:23 +02003660 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3661 goto out;
3662
Willy Tarreaubaaee002006-06-26 02:48:02 +02003663 if (*(args[4]) == 0) {
3664 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3665 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003666 err_code |= ERR_ALERT | ERR_FATAL;
3667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003668 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003669 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003670 curproxy->capture_name = strdup(args[2]);
3671 curproxy->capture_namelen = strlen(curproxy->capture_name);
3672 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003673 curproxy->to_log |= LW_COOKIE;
3674 }
3675 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3676 struct cap_hdr *hdr;
3677
3678 if (curproxy == &defproxy) {
3679 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 +02003680 err_code |= ERR_ALERT | ERR_FATAL;
3681 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003682 }
3683
William Lallemand1a748ae2015-05-19 16:37:23 +02003684 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3685 goto out;
3686
Willy Tarreaubaaee002006-06-26 02:48:02 +02003687 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3688 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3689 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003690 err_code |= ERR_ALERT | ERR_FATAL;
3691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003692 }
3693
3694 hdr = calloc(sizeof(struct cap_hdr), 1);
3695 hdr->next = curproxy->req_cap;
3696 hdr->name = strdup(args[3]);
3697 hdr->namelen = strlen(args[3]);
3698 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003699 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003700 hdr->index = curproxy->nb_req_cap++;
3701 curproxy->req_cap = hdr;
3702 curproxy->to_log |= LW_REQHDR;
3703 }
3704 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3705 struct cap_hdr *hdr;
3706
3707 if (curproxy == &defproxy) {
3708 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 +02003709 err_code |= ERR_ALERT | ERR_FATAL;
3710 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003711 }
3712
William Lallemand1a748ae2015-05-19 16:37:23 +02003713 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3714 goto out;
3715
Willy Tarreaubaaee002006-06-26 02:48:02 +02003716 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3717 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3718 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 }
3722 hdr = calloc(sizeof(struct cap_hdr), 1);
3723 hdr->next = curproxy->rsp_cap;
3724 hdr->name = strdup(args[3]);
3725 hdr->namelen = strlen(args[3]);
3726 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003727 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003728 hdr->index = curproxy->nb_rsp_cap++;
3729 curproxy->rsp_cap = hdr;
3730 curproxy->to_log |= LW_RSPHDR;
3731 }
3732 else {
3733 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3734 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003735 err_code |= ERR_ALERT | ERR_FATAL;
3736 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003737 }
3738 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003739 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003740 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003741 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003742
William Lallemanddf1425a2015-04-28 20:17:49 +02003743 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3744 goto out;
3745
Willy Tarreaubaaee002006-06-26 02:48:02 +02003746 if (*(args[1]) == 0) {
3747 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3748 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_ALERT | ERR_FATAL;
3750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003751 }
3752 curproxy->conn_retries = atol(args[1]);
3753 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003754 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003755 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003756
3757 if (curproxy == &defproxy) {
3758 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3759 err_code |= ERR_ALERT | ERR_FATAL;
3760 goto out;
3761 }
3762
Willy Tarreau20b0de52012-12-24 15:45:22 +01003763 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003764 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003765 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3766 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3767 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3768 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003769 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 +01003770 file, linenum, args[0]);
3771 err_code |= ERR_WARN;
3772 }
3773
Willy Tarreauff011f22011-01-06 17:51:27 +01003774 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003775
Willy Tarreauff011f22011-01-06 17:51:27 +01003776 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003777 err_code |= ERR_ALERT | ERR_ABORT;
3778 goto out;
3779 }
3780
Willy Tarreau5002f572014-04-23 01:32:02 +02003781 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003782 err_code |= warnif_cond_conflicts(rule->cond,
3783 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3784 file, linenum);
3785
Willy Tarreauff011f22011-01-06 17:51:27 +01003786 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003787 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003788 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003789 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003790
3791 if (curproxy == &defproxy) {
3792 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
3795 }
3796
3797 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003798 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003799 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3800 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003801 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3802 file, linenum, args[0]);
3803 err_code |= ERR_WARN;
3804 }
3805
3806 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3807
3808 if (!rule) {
3809 err_code |= ERR_ALERT | ERR_ABORT;
3810 goto out;
3811 }
3812
3813 err_code |= warnif_cond_conflicts(rule->cond,
3814 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3815 file, linenum);
3816
3817 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3818 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003819 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3820 /* set the header name and length into the proxy structure */
3821 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3822 err_code |= ERR_WARN;
3823
3824 if (!*args[1]) {
3825 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3826 file, linenum, args[0]);
3827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
3829 }
3830
3831 /* set the desired header name */
3832 free(curproxy->server_id_hdr_name);
3833 curproxy->server_id_hdr_name = strdup(args[1]);
3834 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3835 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003836 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003837 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003838
Willy Tarreaub099aca2008-10-12 17:26:37 +02003839 if (curproxy == &defproxy) {
3840 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003841 err_code |= ERR_ALERT | ERR_FATAL;
3842 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003843 }
3844
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003845 /* emulate "block" using "http-request block". Since these rules are supposed to
3846 * be processed before all http-request rules, we put them into their own list
3847 * and will insert them at the end.
3848 */
3849 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3850 if (!rule) {
3851 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003852 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003853 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003854 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3855 err_code |= warnif_cond_conflicts(rule->cond,
3856 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3857 file, linenum);
3858 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003859
3860 if (!already_warned(WARN_BLOCK_DEPRECATED))
3861 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]);
3862
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003863 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003864 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003865 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003866
Cyril Bonté99ed3272010-01-24 23:29:44 +01003867 if (curproxy == &defproxy) {
3868 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3869 err_code |= ERR_ALERT | ERR_FATAL;
3870 goto out;
3871 }
3872
Willy Tarreaube4653b2015-05-28 15:26:58 +02003873 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003874 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3875 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003876 err_code |= ERR_ALERT | ERR_FATAL;
3877 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003878 }
3879
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003880 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003881 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003882 err_code |= warnif_cond_conflicts(rule->cond,
3883 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3884 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003885 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003886 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003887 struct switching_rule *rule;
3888
Willy Tarreaub099aca2008-10-12 17:26:37 +02003889 if (curproxy == &defproxy) {
3890 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003891 err_code |= ERR_ALERT | ERR_FATAL;
3892 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003893 }
3894
Willy Tarreau55ea7572007-06-17 19:56:27 +02003895 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003896 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003897
3898 if (*(args[1]) == 0) {
3899 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003900 err_code |= ERR_ALERT | ERR_FATAL;
3901 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003902 }
3903
Willy Tarreauf51658d2014-04-23 01:21:56 +02003904 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3905 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3906 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3907 file, linenum, errmsg);
3908 err_code |= ERR_ALERT | ERR_FATAL;
3909 goto out;
3910 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003911
Willy Tarreauf51658d2014-04-23 01:21:56 +02003912 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003913 }
3914
3915 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3916 rule->cond = cond;
3917 rule->be.name = strdup(args[1]);
3918 LIST_INIT(&rule->list);
3919 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3920 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003921 else if (strcmp(args[0], "use-server") == 0) {
3922 struct server_rule *rule;
3923
3924 if (curproxy == &defproxy) {
3925 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3926 err_code |= ERR_ALERT | ERR_FATAL;
3927 goto out;
3928 }
3929
3930 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3931 err_code |= ERR_WARN;
3932
3933 if (*(args[1]) == 0) {
3934 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
3937 }
3938
3939 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3940 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3941 file, linenum, args[0]);
3942 err_code |= ERR_ALERT | ERR_FATAL;
3943 goto out;
3944 }
3945
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003946 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3947 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3948 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003949 err_code |= ERR_ALERT | ERR_FATAL;
3950 goto out;
3951 }
3952
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003953 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003954
3955 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3956 rule->cond = cond;
3957 rule->srv.name = strdup(args[1]);
3958 LIST_INIT(&rule->list);
3959 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3960 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3961 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003962 else if ((!strcmp(args[0], "force-persist")) ||
3963 (!strcmp(args[0], "ignore-persist"))) {
3964 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003965
3966 if (curproxy == &defproxy) {
3967 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3968 err_code |= ERR_ALERT | ERR_FATAL;
3969 goto out;
3970 }
3971
3972 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3973 err_code |= ERR_WARN;
3974
Willy Tarreauef6494c2010-01-28 17:12:36 +01003975 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003976 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3977 file, linenum, args[0]);
3978 err_code |= ERR_ALERT | ERR_FATAL;
3979 goto out;
3980 }
3981
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003982 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3983 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3984 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
3987 }
3988
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003989 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3990 * where force-persist is applied.
3991 */
3992 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003993
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003994 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003995 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003996 if (!strcmp(args[0], "force-persist")) {
3997 rule->type = PERSIST_TYPE_FORCE;
3998 } else {
3999 rule->type = PERSIST_TYPE_IGNORE;
4000 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004001 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004002 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004003 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004004 else if (!strcmp(args[0], "stick-table")) {
4005 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004006 struct proxy *other;
4007
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004008 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004009 if (other) {
4010 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4011 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4012 err_code |= ERR_ALERT | ERR_FATAL;
4013 goto out;
4014 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004015
Emeric Brun32da3c42010-09-23 18:39:19 +02004016 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004017 curproxy->table.type = (unsigned int)-1;
4018 while (*args[myidx]) {
4019 const char *err;
4020
4021 if (strcmp(args[myidx], "size") == 0) {
4022 myidx++;
4023 if (!*(args[myidx])) {
4024 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4025 file, linenum, args[myidx-1]);
4026 err_code |= ERR_ALERT | ERR_FATAL;
4027 goto out;
4028 }
4029 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4030 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4031 file, linenum, *err, args[myidx-1]);
4032 err_code |= ERR_ALERT | ERR_FATAL;
4033 goto out;
4034 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004035 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004036 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004037 else if (strcmp(args[myidx], "peers") == 0) {
4038 myidx++;
Godbach50523162013-12-11 19:48:57 +08004039 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004040 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4041 file, linenum, args[myidx-1]);
4042 err_code |= ERR_ALERT | ERR_FATAL;
4043 goto out;
Godbach50523162013-12-11 19:48:57 +08004044 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004045 curproxy->table.peers.name = strdup(args[myidx++]);
4046 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004047 else if (strcmp(args[myidx], "expire") == 0) {
4048 myidx++;
4049 if (!*(args[myidx])) {
4050 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4051 file, linenum, args[myidx-1]);
4052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
4054 }
4055 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4056 if (err) {
4057 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4058 file, linenum, *err, args[myidx-1]);
4059 err_code |= ERR_ALERT | ERR_FATAL;
4060 goto out;
4061 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004062 if (val > INT_MAX) {
4063 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4064 file, linenum, val);
4065 err_code |= ERR_ALERT | ERR_FATAL;
4066 goto out;
4067 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004068 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004069 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004070 }
4071 else if (strcmp(args[myidx], "nopurge") == 0) {
4072 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004073 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004074 }
4075 else if (strcmp(args[myidx], "type") == 0) {
4076 myidx++;
4077 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4078 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4079 file, linenum, args[myidx]);
4080 err_code |= ERR_ALERT | ERR_FATAL;
4081 goto out;
4082 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004083 /* myidx already points to next arg */
4084 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004085 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004086 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004087 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004088
4089 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004090 nw = args[myidx];
4091 while (*nw) {
4092 /* the "store" keyword supports a comma-separated list */
4093 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004094 sa = NULL; /* store arg */
4095 while (*nw && *nw != ',') {
4096 if (*nw == '(') {
4097 *nw = 0;
4098 sa = ++nw;
4099 while (*nw != ')') {
4100 if (!*nw) {
4101 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4102 file, linenum, args[0], cw);
4103 err_code |= ERR_ALERT | ERR_FATAL;
4104 goto out;
4105 }
4106 nw++;
4107 }
4108 *nw = '\0';
4109 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004110 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004111 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004112 if (*nw)
4113 *nw++ = '\0';
4114 type = stktable_get_data_type(cw);
4115 if (type < 0) {
4116 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4117 file, linenum, args[0], cw);
4118 err_code |= ERR_ALERT | ERR_FATAL;
4119 goto out;
4120 }
Willy Tarreauac782882010-06-20 10:41:54 +02004121
4122 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4123 switch (err) {
4124 case PE_NONE: break;
4125 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004126 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4127 file, linenum, args[0], cw);
4128 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004129 break;
4130
4131 case PE_ARG_MISSING:
4132 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4133 file, linenum, args[0], cw);
4134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
4136
4137 case PE_ARG_NOT_USED:
4138 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4139 file, linenum, args[0], cw);
4140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
4142
4143 default:
4144 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4145 file, linenum, args[0], cw);
4146 err_code |= ERR_ALERT | ERR_FATAL;
4147 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004148 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004149 }
4150 myidx++;
4151 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004152 else {
4153 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4154 file, linenum, args[myidx]);
4155 err_code |= ERR_ALERT | ERR_FATAL;
4156 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004157 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004158 }
4159
4160 if (!curproxy->table.size) {
4161 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4162 file, linenum);
4163 err_code |= ERR_ALERT | ERR_FATAL;
4164 goto out;
4165 }
4166
4167 if (curproxy->table.type == (unsigned int)-1) {
4168 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4169 file, linenum);
4170 err_code |= ERR_ALERT | ERR_FATAL;
4171 goto out;
4172 }
4173 }
4174 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004175 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004176 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004177 int myidx = 0;
4178 const char *name = NULL;
4179 int flags;
4180
4181 if (curproxy == &defproxy) {
4182 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4183 err_code |= ERR_ALERT | ERR_FATAL;
4184 goto out;
4185 }
4186
4187 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4188 err_code |= ERR_WARN;
4189 goto out;
4190 }
4191
4192 myidx++;
4193 if ((strcmp(args[myidx], "store") == 0) ||
4194 (strcmp(args[myidx], "store-request") == 0)) {
4195 myidx++;
4196 flags = STK_IS_STORE;
4197 }
4198 else if (strcmp(args[myidx], "store-response") == 0) {
4199 myidx++;
4200 flags = STK_IS_STORE | STK_ON_RSP;
4201 }
4202 else if (strcmp(args[myidx], "match") == 0) {
4203 myidx++;
4204 flags = STK_IS_MATCH;
4205 }
4206 else if (strcmp(args[myidx], "on") == 0) {
4207 myidx++;
4208 flags = STK_IS_MATCH | STK_IS_STORE;
4209 }
4210 else {
4211 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4212 err_code |= ERR_ALERT | ERR_FATAL;
4213 goto out;
4214 }
4215
4216 if (*(args[myidx]) == 0) {
4217 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4218 err_code |= ERR_ALERT | ERR_FATAL;
4219 goto out;
4220 }
4221
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004222 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004223 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004224 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004225 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004226 err_code |= ERR_ALERT | ERR_FATAL;
4227 goto out;
4228 }
4229
4230 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004231 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4232 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4233 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004234 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004235 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004236 goto out;
4237 }
4238 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004239 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4240 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4241 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004242 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004243 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004244 goto out;
4245 }
4246 }
4247
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004248 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004249 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004250
Emeric Brunb982a3d2010-01-04 15:45:53 +01004251 if (strcmp(args[myidx], "table") == 0) {
4252 myidx++;
4253 name = args[myidx++];
4254 }
4255
Willy Tarreauef6494c2010-01-28 17:12:36 +01004256 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004257 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4258 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4259 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004260 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004261 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004262 goto out;
4263 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004264 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004265 else if (*(args[myidx])) {
4266 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4267 file, linenum, args[0], args[myidx]);
4268 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004269 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004270 goto out;
4271 }
Emeric Brun97679e72010-09-23 17:56:44 +02004272 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004273 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004274 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004275 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004276
Emeric Brunb982a3d2010-01-04 15:45:53 +01004277 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4278 rule->cond = cond;
4279 rule->expr = expr;
4280 rule->flags = flags;
4281 rule->table.name = name ? strdup(name) : NULL;
4282 LIST_INIT(&rule->list);
4283 if (flags & STK_ON_RSP)
4284 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4285 else
4286 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4287 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004288 else if (!strcmp(args[0], "stats")) {
4289 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4290 curproxy->uri_auth = NULL; /* we must detach from the default config */
4291
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004292 if (!*args[1]) {
4293 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004294 } else if (!strcmp(args[1], "admin")) {
4295 struct stats_admin_rule *rule;
4296
4297 if (curproxy == &defproxy) {
4298 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
4301 }
4302
4303 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4304 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4305 err_code |= ERR_ALERT | ERR_ABORT;
4306 goto out;
4307 }
4308
4309 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4310 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4311 file, linenum, args[0], args[1]);
4312 err_code |= ERR_ALERT | ERR_FATAL;
4313 goto out;
4314 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004315 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4316 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4317 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004318 err_code |= ERR_ALERT | ERR_FATAL;
4319 goto out;
4320 }
4321
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004322 err_code |= warnif_cond_conflicts(cond,
4323 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4324 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004325
4326 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4327 rule->cond = cond;
4328 LIST_INIT(&rule->list);
4329 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004330 } else if (!strcmp(args[1], "uri")) {
4331 if (*(args[2]) == 0) {
4332 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004333 err_code |= ERR_ALERT | ERR_FATAL;
4334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004335 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4336 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004337 err_code |= ERR_ALERT | ERR_ABORT;
4338 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004339 }
4340 } else if (!strcmp(args[1], "realm")) {
4341 if (*(args[2]) == 0) {
4342 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004343 err_code |= ERR_ALERT | ERR_FATAL;
4344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004345 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4346 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004347 err_code |= ERR_ALERT | ERR_ABORT;
4348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004349 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004350 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004351 unsigned interval;
4352
4353 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4354 if (err) {
4355 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4356 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004357 err_code |= ERR_ALERT | ERR_FATAL;
4358 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004359 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4360 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004361 err_code |= ERR_ALERT | ERR_ABORT;
4362 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004363 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004364 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004365 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004366
4367 if (curproxy == &defproxy) {
4368 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4369 err_code |= ERR_ALERT | ERR_FATAL;
4370 goto out;
4371 }
4372
4373 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4374 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4375 err_code |= ERR_ALERT | ERR_ABORT;
4376 goto out;
4377 }
4378
Willy Tarreauff011f22011-01-06 17:51:27 +01004379 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004380 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004381 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4382 file, linenum, args[0]);
4383 err_code |= ERR_WARN;
4384 }
4385
Willy Tarreauff011f22011-01-06 17:51:27 +01004386 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004387
Willy Tarreauff011f22011-01-06 17:51:27 +01004388 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004389 err_code |= ERR_ALERT | ERR_ABORT;
4390 goto out;
4391 }
4392
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004393 err_code |= warnif_cond_conflicts(rule->cond,
4394 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4395 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004396 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004397
Willy Tarreaubaaee002006-06-26 02:48:02 +02004398 } else if (!strcmp(args[1], "auth")) {
4399 if (*(args[2]) == 0) {
4400 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004401 err_code |= ERR_ALERT | ERR_FATAL;
4402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004403 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4404 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004405 err_code |= ERR_ALERT | ERR_ABORT;
4406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004407 }
4408 } else if (!strcmp(args[1], "scope")) {
4409 if (*(args[2]) == 0) {
4410 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004411 err_code |= ERR_ALERT | ERR_FATAL;
4412 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004413 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4414 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004415 err_code |= ERR_ALERT | ERR_ABORT;
4416 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004417 }
4418 } else if (!strcmp(args[1], "enable")) {
4419 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4420 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004421 err_code |= ERR_ALERT | ERR_ABORT;
4422 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004423 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004424 } else if (!strcmp(args[1], "hide-version")) {
4425 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4426 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004427 err_code |= ERR_ALERT | ERR_ABORT;
4428 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004429 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004430 } else if (!strcmp(args[1], "show-legends")) {
4431 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4432 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4433 err_code |= ERR_ALERT | ERR_ABORT;
4434 goto out;
4435 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004436 } else if (!strcmp(args[1], "show-node")) {
4437
4438 if (*args[2]) {
4439 int i;
4440 char c;
4441
4442 for (i=0; args[2][i]; i++) {
4443 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004444 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4445 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004446 break;
4447 }
4448
4449 if (!i || args[2][i]) {
4450 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4451 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4452 file, linenum, args[0], args[1]);
4453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
4455 }
4456 }
4457
4458 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4459 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4460 err_code |= ERR_ALERT | ERR_ABORT;
4461 goto out;
4462 }
4463 } else if (!strcmp(args[1], "show-desc")) {
4464 char *desc = NULL;
4465
4466 if (*args[2]) {
4467 int i, len=0;
4468 char *d;
4469
Willy Tarreau348acfe2014-04-14 15:00:39 +02004470 for (i = 2; *args[i]; i++)
4471 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004472
4473 desc = d = (char *)calloc(1, len);
4474
Willy Tarreau348acfe2014-04-14 15:00:39 +02004475 d += snprintf(d, desc + len - d, "%s", args[2]);
4476 for (i = 3; *args[i]; i++)
4477 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004478 }
4479
4480 if (!*args[2] && !global.desc)
4481 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4482 file, linenum, args[1]);
4483 else {
4484 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4485 free(desc);
4486 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4487 err_code |= ERR_ALERT | ERR_ABORT;
4488 goto out;
4489 }
4490 free(desc);
4491 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004492 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004493stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004494 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 +01004495 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004496 err_code |= ERR_ALERT | ERR_FATAL;
4497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004498 }
4499 }
4500 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004501 int optnum;
4502
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004503 if (*(args[1]) == '\0') {
4504 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4505 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004506 err_code |= ERR_ALERT | ERR_FATAL;
4507 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004508 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004509
4510 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4511 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004512 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4513 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4514 file, linenum, cfg_opts[optnum].name);
4515 err_code |= ERR_ALERT | ERR_FATAL;
4516 goto out;
4517 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004518 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4519 goto out;
4520
Willy Tarreau93893792009-07-23 13:19:11 +02004521 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4522 err_code |= ERR_WARN;
4523 goto out;
4524 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004525
Willy Tarreau3842f002009-06-14 11:39:52 +02004526 curproxy->no_options &= ~cfg_opts[optnum].val;
4527 curproxy->options &= ~cfg_opts[optnum].val;
4528
4529 switch (kwm) {
4530 case KWM_STD:
4531 curproxy->options |= cfg_opts[optnum].val;
4532 break;
4533 case KWM_NO:
4534 curproxy->no_options |= cfg_opts[optnum].val;
4535 break;
4536 case KWM_DEF: /* already cleared */
4537 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004538 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004539
Willy Tarreau93893792009-07-23 13:19:11 +02004540 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004541 }
4542 }
4543
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004544 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4545 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004546 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4547 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4548 file, linenum, cfg_opts2[optnum].name);
4549 err_code |= ERR_ALERT | ERR_FATAL;
4550 goto out;
4551 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004552 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4553 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004554 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4555 err_code |= ERR_WARN;
4556 goto out;
4557 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004558
Willy Tarreau3842f002009-06-14 11:39:52 +02004559 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4560 curproxy->options2 &= ~cfg_opts2[optnum].val;
4561
4562 switch (kwm) {
4563 case KWM_STD:
4564 curproxy->options2 |= cfg_opts2[optnum].val;
4565 break;
4566 case KWM_NO:
4567 curproxy->no_options2 |= cfg_opts2[optnum].val;
4568 break;
4569 case KWM_DEF: /* already cleared */
4570 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004571 }
Willy Tarreau93893792009-07-23 13:19:11 +02004572 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004573 }
4574 }
4575
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004576 /* HTTP options override each other. They can be cancelled using
4577 * "no option xxx" which only switches to default mode if the mode
4578 * was this one (useful for cancelling options set in defaults
4579 * sections).
4580 */
4581 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004582 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4583 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004584 if (kwm == KWM_STD) {
4585 curproxy->options &= ~PR_O_HTTP_MODE;
4586 curproxy->options |= PR_O_HTTP_PCL;
4587 goto out;
4588 }
4589 else if (kwm == KWM_NO) {
4590 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4591 curproxy->options &= ~PR_O_HTTP_MODE;
4592 goto out;
4593 }
4594 }
4595 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004596 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4597 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004598 if (kwm == KWM_STD) {
4599 curproxy->options &= ~PR_O_HTTP_MODE;
4600 curproxy->options |= PR_O_HTTP_FCL;
4601 goto out;
4602 }
4603 else if (kwm == KWM_NO) {
4604 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4605 curproxy->options &= ~PR_O_HTTP_MODE;
4606 goto out;
4607 }
4608 }
4609 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004610 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4611 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004612 if (kwm == KWM_STD) {
4613 curproxy->options &= ~PR_O_HTTP_MODE;
4614 curproxy->options |= PR_O_HTTP_SCL;
4615 goto out;
4616 }
4617 else if (kwm == KWM_NO) {
4618 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4619 curproxy->options &= ~PR_O_HTTP_MODE;
4620 goto out;
4621 }
4622 }
4623 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004624 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4625 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004626 if (kwm == KWM_STD) {
4627 curproxy->options &= ~PR_O_HTTP_MODE;
4628 curproxy->options |= PR_O_HTTP_KAL;
4629 goto out;
4630 }
4631 else if (kwm == KWM_NO) {
4632 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4633 curproxy->options &= ~PR_O_HTTP_MODE;
4634 goto out;
4635 }
4636 }
4637 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004638 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4639 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004640 if (kwm == KWM_STD) {
4641 curproxy->options &= ~PR_O_HTTP_MODE;
4642 curproxy->options |= PR_O_HTTP_TUN;
4643 goto out;
4644 }
4645 else if (kwm == KWM_NO) {
4646 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4647 curproxy->options &= ~PR_O_HTTP_MODE;
4648 goto out;
4649 }
4650 }
4651
Joseph Lynch726ab712015-05-11 23:25:34 -07004652 /* Redispatch can take an integer argument that control when the
4653 * resispatch occurs. All values are relative to the retries option.
4654 * This can be cancelled using "no option xxx".
4655 */
4656 if (strcmp(args[1], "redispatch") == 0) {
4657 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4658 err_code |= ERR_WARN;
4659 goto out;
4660 }
4661
4662 curproxy->no_options &= ~PR_O_REDISP;
4663 curproxy->options &= ~PR_O_REDISP;
4664
4665 switch (kwm) {
4666 case KWM_STD:
4667 curproxy->options |= PR_O_REDISP;
4668 curproxy->redispatch_after = -1;
4669 if(*args[2]) {
4670 curproxy->redispatch_after = atol(args[2]);
4671 }
4672 break;
4673 case KWM_NO:
4674 curproxy->no_options |= PR_O_REDISP;
4675 curproxy->redispatch_after = 0;
4676 break;
4677 case KWM_DEF: /* already cleared */
4678 break;
4679 }
4680 goto out;
4681 }
4682
Willy Tarreau3842f002009-06-14 11:39:52 +02004683 if (kwm != KWM_STD) {
4684 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004685 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004686 err_code |= ERR_ALERT | ERR_FATAL;
4687 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004688 }
4689
Emeric Brun3a058f32009-06-30 18:26:00 +02004690 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004691 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004692 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004693 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004694 if (*(args[2]) != '\0') {
4695 if (!strcmp(args[2], "clf")) {
4696 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004697 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004698 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004699 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004700 err_code |= ERR_ALERT | ERR_FATAL;
4701 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004702 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004703 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4704 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004705 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004706 if (curproxy->conf.logformat_string != default_http_log_format &&
4707 curproxy->conf.logformat_string != default_tcp_log_format &&
4708 curproxy->conf.logformat_string != clf_http_log_format)
4709 free(curproxy->conf.logformat_string);
4710 curproxy->conf.logformat_string = logformat;
4711
4712 free(curproxy->conf.lfs_file);
4713 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4714 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004715 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004716 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004717 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004718 if (curproxy->conf.logformat_string != default_http_log_format &&
4719 curproxy->conf.logformat_string != default_tcp_log_format &&
4720 curproxy->conf.logformat_string != clf_http_log_format)
4721 free(curproxy->conf.logformat_string);
4722 curproxy->conf.logformat_string = default_tcp_log_format;
4723
4724 free(curproxy->conf.lfs_file);
4725 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4726 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004727
4728 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4729 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004730 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004731 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004732 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004733 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004734 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004735
William Lallemanddf1425a2015-04-28 20:17:49 +02004736 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4737 goto out;
4738
Willy Tarreau13943ab2006-12-31 00:24:10 +01004739 if (curproxy->cap & PR_CAP_FE)
4740 curproxy->options |= PR_O_TCP_CLI_KA;
4741 if (curproxy->cap & PR_CAP_BE)
4742 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 }
4744 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004745 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004746 err_code |= ERR_WARN;
4747
Willy Tarreaubaaee002006-06-26 02:48:02 +02004748 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004749 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004750 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004751 curproxy->options2 &= ~PR_O2_CHK_ANY;
4752 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004753 if (!*args[2]) { /* no argument */
4754 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4755 curproxy->check_len = strlen(DEF_CHECK_REQ);
4756 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004757 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 curproxy->check_req = (char *)malloc(reqlen);
4759 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004760 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004761 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004762 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763 if (*args[4])
4764 reqlen += strlen(args[4]);
4765 else
4766 reqlen += strlen("HTTP/1.0");
4767
4768 curproxy->check_req = (char *)malloc(reqlen);
4769 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004770 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004771 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004772 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4773 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004774 }
4775 else if (!strcmp(args[1], "ssl-hello-chk")) {
4776 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004777 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004778 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004779
Willy Tarreaua534fea2008-08-03 12:19:50 +02004780 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004781 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004782 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004783 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004784
4785 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004787 }
Willy Tarreau23677902007-05-08 23:50:35 +02004788 else if (!strcmp(args[1], "smtpchk")) {
4789 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004790 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004791 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004792 curproxy->options2 &= ~PR_O2_CHK_ANY;
4793 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004794
4795 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4796 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4797 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4798 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4799 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4800 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4801 curproxy->check_req = (char *)malloc(reqlen);
4802 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4803 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4804 } else {
4805 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4806 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4807 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4808 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4809 }
4810 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004811 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4812 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004813 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004814 else if (!strcmp(args[1], "pgsql-check")) {
4815 /* use PostgreSQL request to check servers' health */
4816 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4817 err_code |= ERR_WARN;
4818
4819 free(curproxy->check_req);
4820 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004821 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004822 curproxy->options2 |= PR_O2_PGSQL_CHK;
4823
4824 if (*(args[2])) {
4825 int cur_arg = 2;
4826
4827 while (*(args[cur_arg])) {
4828 if (strcmp(args[cur_arg], "user") == 0) {
4829 char * packet;
4830 uint32_t packet_len;
4831 uint32_t pv;
4832
4833 /* suboption header - needs additional argument for it */
4834 if (*(args[cur_arg+1]) == 0) {
4835 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4836 file, linenum, args[0], args[1], args[cur_arg]);
4837 err_code |= ERR_ALERT | ERR_FATAL;
4838 goto out;
4839 }
4840
4841 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4842 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4843 pv = htonl(0x30000); /* protocol version 3.0 */
4844
4845 packet = (char*) calloc(1, packet_len);
4846
4847 memcpy(packet + 4, &pv, 4);
4848
4849 /* copy "user" */
4850 memcpy(packet + 8, "user", 4);
4851
4852 /* copy username */
4853 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4854
4855 free(curproxy->check_req);
4856 curproxy->check_req = packet;
4857 curproxy->check_len = packet_len;
4858
4859 packet_len = htonl(packet_len);
4860 memcpy(packet, &packet_len, 4);
4861 cur_arg += 2;
4862 } else {
4863 /* unknown suboption - catchall */
4864 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4865 file, linenum, args[0], args[1]);
4866 err_code |= ERR_ALERT | ERR_FATAL;
4867 goto out;
4868 }
4869 } /* end while loop */
4870 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004871 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4872 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004873 }
4874
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004875 else if (!strcmp(args[1], "redis-check")) {
4876 /* use REDIS PING request to check servers' health */
4877 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4878 err_code |= ERR_WARN;
4879
4880 free(curproxy->check_req);
4881 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004882 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004883 curproxy->options2 |= PR_O2_REDIS_CHK;
4884
4885 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4886 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4887 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004888
4889 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4890 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004891 }
4892
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004893 else if (!strcmp(args[1], "mysql-check")) {
4894 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004895 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4896 err_code |= ERR_WARN;
4897
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004898 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004899 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004900 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004901 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004902
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004903 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004904 * const char mysql40_client_auth_pkt[] = {
4905 * "\x0e\x00\x00" // packet length
4906 * "\x01" // packet number
4907 * "\x00\x00" // client capabilities
4908 * "\x00\x00\x01" // max packet
4909 * "haproxy\x00" // username (null terminated string)
4910 * "\x00" // filler (always 0x00)
4911 * "\x01\x00\x00" // packet length
4912 * "\x00" // packet number
4913 * "\x01" // COM_QUIT command
4914 * };
4915 */
4916
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004917 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4918 * const char mysql41_client_auth_pkt[] = {
4919 * "\x0e\x00\x00\" // packet length
4920 * "\x01" // packet number
4921 * "\x00\x00\x00\x00" // client capabilities
4922 * "\x00\x00\x00\x01" // max packet
4923 * "\x21" // character set (UTF-8)
4924 * char[23] // All zeroes
4925 * "haproxy\x00" // username (null terminated string)
4926 * "\x00" // filler (always 0x00)
4927 * "\x01\x00\x00" // packet length
4928 * "\x00" // packet number
4929 * "\x01" // COM_QUIT command
4930 * };
4931 */
4932
4933
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004934 if (*(args[2])) {
4935 int cur_arg = 2;
4936
4937 while (*(args[cur_arg])) {
4938 if (strcmp(args[cur_arg], "user") == 0) {
4939 char *mysqluser;
4940 int packetlen, reqlen, userlen;
4941
4942 /* suboption header - needs additional argument for it */
4943 if (*(args[cur_arg+1]) == 0) {
4944 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4945 file, linenum, args[0], args[1], args[cur_arg]);
4946 err_code |= ERR_ALERT | ERR_FATAL;
4947 goto out;
4948 }
4949 mysqluser = args[cur_arg + 1];
4950 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004951
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004952 if (*(args[cur_arg+2])) {
4953 if (!strcmp(args[cur_arg+2], "post-41")) {
4954 packetlen = userlen + 7 + 27;
4955 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004956
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004957 free(curproxy->check_req);
4958 curproxy->check_req = (char *)calloc(1, reqlen);
4959 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004960
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004961 snprintf(curproxy->check_req, 4, "%c%c%c",
4962 ((unsigned char) packetlen & 0xff),
4963 ((unsigned char) (packetlen >> 8) & 0xff),
4964 ((unsigned char) (packetlen >> 16) & 0xff));
4965
4966 curproxy->check_req[3] = 1;
4967 curproxy->check_req[5] = 130;
4968 curproxy->check_req[11] = 1;
4969 curproxy->check_req[12] = 33;
4970 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4971 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4972 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4973 cur_arg += 3;
4974 } else {
4975 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4976 err_code |= ERR_ALERT | ERR_FATAL;
4977 goto out;
4978 }
4979 } else {
4980 packetlen = userlen + 7;
4981 reqlen = packetlen + 9;
4982
4983 free(curproxy->check_req);
4984 curproxy->check_req = (char *)calloc(1, reqlen);
4985 curproxy->check_len = reqlen;
4986
4987 snprintf(curproxy->check_req, 4, "%c%c%c",
4988 ((unsigned char) packetlen & 0xff),
4989 ((unsigned char) (packetlen >> 8) & 0xff),
4990 ((unsigned char) (packetlen >> 16) & 0xff));
4991
4992 curproxy->check_req[3] = 1;
4993 curproxy->check_req[5] = 128;
4994 curproxy->check_req[8] = 1;
4995 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4996 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4997 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4998 cur_arg += 2;
4999 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005000 } else {
5001 /* unknown suboption - catchall */
5002 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5003 file, linenum, args[0], args[1]);
5004 err_code |= ERR_ALERT | ERR_FATAL;
5005 goto out;
5006 }
5007 } /* end while loop */
5008 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005009 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005010 else if (!strcmp(args[1], "ldap-check")) {
5011 /* use LDAP request to check servers' health */
5012 free(curproxy->check_req);
5013 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005014 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005015 curproxy->options2 |= PR_O2_LDAP_CHK;
5016
5017 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
5018 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5019 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005020 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5021 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005022 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005023 else if (!strcmp(args[1], "tcp-check")) {
5024 /* use raw TCPCHK send/expect to check servers' health */
5025 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5026 err_code |= ERR_WARN;
5027
5028 free(curproxy->check_req);
5029 curproxy->check_req = NULL;
5030 curproxy->options2 &= ~PR_O2_CHK_ANY;
5031 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005032 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5033 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005034 }
Simon Horman98637e52014-06-20 12:30:16 +09005035 else if (!strcmp(args[1], "external-check")) {
5036 /* excute an external command to check servers' health */
5037 free(curproxy->check_req);
5038 curproxy->check_req = NULL;
5039 curproxy->options2 &= ~PR_O2_CHK_ANY;
5040 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005041 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5042 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005043 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005044 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005045 int cur_arg;
5046
5047 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5048 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005049 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005050
Willy Tarreau87cf5142011-08-19 22:57:24 +02005051 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005052
5053 free(curproxy->fwdfor_hdr_name);
5054 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5055 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5056
5057 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5058 cur_arg = 2;
5059 while (*(args[cur_arg])) {
5060 if (!strcmp(args[cur_arg], "except")) {
5061 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005062 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005063 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5064 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005065 err_code |= ERR_ALERT | ERR_FATAL;
5066 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005067 }
5068 /* flush useless bits */
5069 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005070 cur_arg += 2;
5071 } else if (!strcmp(args[cur_arg], "header")) {
5072 /* suboption header - needs additional argument for it */
5073 if (*(args[cur_arg+1]) == 0) {
5074 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5075 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005076 err_code |= ERR_ALERT | ERR_FATAL;
5077 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005078 }
5079 free(curproxy->fwdfor_hdr_name);
5080 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5081 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5082 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005083 } else if (!strcmp(args[cur_arg], "if-none")) {
5084 curproxy->options &= ~PR_O_FF_ALWAYS;
5085 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005086 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005087 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005088 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005089 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005090 err_code |= ERR_ALERT | ERR_FATAL;
5091 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005092 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005093 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005094 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005095 else if (!strcmp(args[1], "originalto")) {
5096 int cur_arg;
5097
5098 /* insert x-original-to field, but not for the IP address listed as an except.
5099 * set default options (ie: bitfield, header name, etc)
5100 */
5101
5102 curproxy->options |= PR_O_ORGTO;
5103
5104 free(curproxy->orgto_hdr_name);
5105 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5106 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5107
Willy Tarreau87cf5142011-08-19 22:57:24 +02005108 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005109 cur_arg = 2;
5110 while (*(args[cur_arg])) {
5111 if (!strcmp(args[cur_arg], "except")) {
5112 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005113 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 +02005114 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5115 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005116 err_code |= ERR_ALERT | ERR_FATAL;
5117 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005118 }
5119 /* flush useless bits */
5120 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5121 cur_arg += 2;
5122 } else if (!strcmp(args[cur_arg], "header")) {
5123 /* suboption header - needs additional argument for it */
5124 if (*(args[cur_arg+1]) == 0) {
5125 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5126 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005127 err_code |= ERR_ALERT | ERR_FATAL;
5128 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005129 }
5130 free(curproxy->orgto_hdr_name);
5131 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5132 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5133 cur_arg += 2;
5134 } else {
5135 /* unknown suboption - catchall */
5136 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5137 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005138 err_code |= ERR_ALERT | ERR_FATAL;
5139 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005140 }
5141 } /* end while loop */
5142 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005143 else {
5144 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005145 err_code |= ERR_ALERT | ERR_FATAL;
5146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 }
Willy Tarreau93893792009-07-23 13:19:11 +02005148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005149 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005150 else if (!strcmp(args[0], "default_backend")) {
5151 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005152 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005153
5154 if (*(args[1]) == 0) {
5155 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005156 err_code |= ERR_ALERT | ERR_FATAL;
5157 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005158 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005159 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005160 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005161
5162 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5163 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005164 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005165 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005166 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005167 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005168
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005169 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5170 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 +01005171 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005172 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005173 /* enable reconnections to dispatch */
5174 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005175
5176 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005178 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005179 else if (!strcmp(args[0], "http-reuse")) {
5180 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5181 err_code |= ERR_WARN;
5182
5183 if (strcmp(args[1], "never") == 0) {
5184 /* enable a graceful server shutdown on an HTTP 404 response */
5185 curproxy->options &= ~PR_O_REUSE_MASK;
5186 curproxy->options |= PR_O_REUSE_NEVR;
5187 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5188 goto out;
5189 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005190 else if (strcmp(args[1], "safe") == 0) {
5191 /* enable a graceful server shutdown on an HTTP 404 response */
5192 curproxy->options &= ~PR_O_REUSE_MASK;
5193 curproxy->options |= PR_O_REUSE_SAFE;
5194 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5195 goto out;
5196 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005197 else if (strcmp(args[1], "aggressive") == 0) {
5198 curproxy->options &= ~PR_O_REUSE_MASK;
5199 curproxy->options |= PR_O_REUSE_AGGR;
5200 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5201 goto out;
5202 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005203 else if (strcmp(args[1], "always") == 0) {
5204 /* enable a graceful server shutdown on an HTTP 404 response */
5205 curproxy->options &= ~PR_O_REUSE_MASK;
5206 curproxy->options |= PR_O_REUSE_ALWS;
5207 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5208 goto out;
5209 }
5210 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005211 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005212 err_code |= ERR_ALERT | ERR_FATAL;
5213 goto out;
5214 }
5215 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005216 else if (!strcmp(args[0], "http-check")) {
5217 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005218 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005219
5220 if (strcmp(args[1], "disable-on-404") == 0) {
5221 /* enable a graceful server shutdown on an HTTP 404 response */
5222 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005223 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5224 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005225 }
Willy Tarreauef781042010-01-27 11:53:01 +01005226 else if (strcmp(args[1], "send-state") == 0) {
5227 /* enable emission of the apparent state of a server in HTTP checks */
5228 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005229 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5230 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005231 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005232 else if (strcmp(args[1], "expect") == 0) {
5233 const char *ptr_arg;
5234 int cur_arg;
5235
5236 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5237 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5238 err_code |= ERR_ALERT | ERR_FATAL;
5239 goto out;
5240 }
5241
5242 cur_arg = 2;
5243 /* consider exclamation marks, sole or at the beginning of a word */
5244 while (*(ptr_arg = args[cur_arg])) {
5245 while (*ptr_arg == '!') {
5246 curproxy->options2 ^= PR_O2_EXP_INV;
5247 ptr_arg++;
5248 }
5249 if (*ptr_arg)
5250 break;
5251 cur_arg++;
5252 }
5253 /* now ptr_arg points to the beginning of a word past any possible
5254 * exclamation mark, and cur_arg is the argument which holds this word.
5255 */
5256 if (strcmp(ptr_arg, "status") == 0) {
5257 if (!*(args[cur_arg + 1])) {
5258 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5259 file, linenum, args[0], args[1], ptr_arg);
5260 err_code |= ERR_ALERT | ERR_FATAL;
5261 goto out;
5262 }
5263 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005264 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005265 curproxy->expect_str = strdup(args[cur_arg + 1]);
5266 }
5267 else if (strcmp(ptr_arg, "string") == 0) {
5268 if (!*(args[cur_arg + 1])) {
5269 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5270 file, linenum, args[0], args[1], ptr_arg);
5271 err_code |= ERR_ALERT | ERR_FATAL;
5272 goto out;
5273 }
5274 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005275 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005276 curproxy->expect_str = strdup(args[cur_arg + 1]);
5277 }
5278 else if (strcmp(ptr_arg, "rstatus") == 0) {
5279 if (!*(args[cur_arg + 1])) {
5280 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5281 file, linenum, args[0], args[1], ptr_arg);
5282 err_code |= ERR_ALERT | ERR_FATAL;
5283 goto out;
5284 }
5285 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005286 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005287 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005288 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005289 free(curproxy->expect_regex);
5290 curproxy->expect_regex = NULL;
5291 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005292 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005293 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5294 error = NULL;
5295 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5296 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5297 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5298 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005299 err_code |= ERR_ALERT | ERR_FATAL;
5300 goto out;
5301 }
5302 }
5303 else if (strcmp(ptr_arg, "rstring") == 0) {
5304 if (!*(args[cur_arg + 1])) {
5305 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5306 file, linenum, args[0], args[1], ptr_arg);
5307 err_code |= ERR_ALERT | ERR_FATAL;
5308 goto out;
5309 }
5310 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005311 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005312 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005313 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005314 free(curproxy->expect_regex);
5315 curproxy->expect_regex = NULL;
5316 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005317 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005318 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5319 error = NULL;
5320 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5321 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5322 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5323 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005324 err_code |= ERR_ALERT | ERR_FATAL;
5325 goto out;
5326 }
5327 }
5328 else {
5329 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5330 file, linenum, args[0], args[1], ptr_arg);
5331 err_code |= ERR_ALERT | ERR_FATAL;
5332 goto out;
5333 }
5334 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005335 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005336 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 +02005337 err_code |= ERR_ALERT | ERR_FATAL;
5338 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005339 }
5340 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005341 else if (!strcmp(args[0], "tcp-check")) {
5342 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5343 err_code |= ERR_WARN;
5344
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005345 if (strcmp(args[1], "comment") == 0) {
5346 int cur_arg;
5347 struct tcpcheck_rule *tcpcheck;
5348
5349 cur_arg = 1;
5350 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5351 tcpcheck->action = TCPCHK_ACT_COMMENT;
5352
5353 if (!*args[cur_arg + 1]) {
5354 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5355 file, linenum, args[cur_arg]);
5356 err_code |= ERR_ALERT | ERR_FATAL;
5357 goto out;
5358 }
5359
5360 tcpcheck->comment = strdup(args[cur_arg + 1]);
5361
5362 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005363 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5364 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005365 }
5366 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005367 const char *ptr_arg;
5368 int cur_arg;
5369 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005370
5371 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005372 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5373 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5374 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5375 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5376 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005377
Willy Tarreau5581c272015-05-13 12:24:53 +02005378 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5379 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5380 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5381 file, linenum);
5382 err_code |= ERR_ALERT | ERR_FATAL;
5383 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005384 }
5385
5386 cur_arg = 2;
5387 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5388 tcpcheck->action = TCPCHK_ACT_CONNECT;
5389
5390 /* parsing each parameters to fill up the rule */
5391 while (*(ptr_arg = args[cur_arg])) {
5392 /* tcp port */
5393 if (strcmp(args[cur_arg], "port") == 0) {
5394 if ( (atol(args[cur_arg + 1]) > 65535) ||
5395 (atol(args[cur_arg + 1]) < 1) ){
5396 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5397 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5398 err_code |= ERR_ALERT | ERR_FATAL;
5399 goto out;
5400 }
5401 tcpcheck->port = atol(args[cur_arg + 1]);
5402 cur_arg += 2;
5403 }
5404 /* send proxy protocol */
5405 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5406 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5407 cur_arg++;
5408 }
5409#ifdef USE_OPENSSL
5410 else if (strcmp(args[cur_arg], "ssl") == 0) {
5411 curproxy->options |= PR_O_TCPCHK_SSL;
5412 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5413 cur_arg++;
5414 }
5415#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005416 /* comment for this tcpcheck line */
5417 else if (strcmp(args[cur_arg], "comment") == 0) {
5418 if (!*args[cur_arg + 1]) {
5419 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5420 file, linenum, args[cur_arg]);
5421 err_code |= ERR_ALERT | ERR_FATAL;
5422 goto out;
5423 }
5424 tcpcheck->comment = strdup(args[cur_arg + 1]);
5425 cur_arg += 2;
5426 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005427 else {
5428#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005429 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 +01005430#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005431 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 +01005432#endif /* USE_OPENSSL */
5433 file, linenum, args[0], args[1], args[cur_arg]);
5434 err_code |= ERR_ALERT | ERR_FATAL;
5435 goto out;
5436 }
5437
5438 }
5439
5440 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5441 }
5442 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005443 if (! *(args[2]) ) {
5444 /* SEND string expected */
5445 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5446 file, linenum, args[0], args[1], args[2]);
5447 err_code |= ERR_ALERT | ERR_FATAL;
5448 goto out;
5449 } else {
5450 struct tcpcheck_rule *tcpcheck;
5451
5452 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5453
5454 tcpcheck->action = TCPCHK_ACT_SEND;
5455 tcpcheck->string_len = strlen(args[2]);
5456 tcpcheck->string = strdup(args[2]);
5457 tcpcheck->expect_regex = NULL;
5458
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005459 /* comment for this tcpcheck line */
5460 if (strcmp(args[3], "comment") == 0) {
5461 if (!*args[4]) {
5462 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5463 file, linenum, args[3]);
5464 err_code |= ERR_ALERT | ERR_FATAL;
5465 goto out;
5466 }
5467 tcpcheck->comment = strdup(args[4]);
5468 }
5469
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005470 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5471 }
5472 }
5473 else if (strcmp(args[1], "send-binary") == 0) {
5474 if (! *(args[2]) ) {
5475 /* SEND binary string expected */
5476 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5477 file, linenum, args[0], args[1], args[2]);
5478 err_code |= ERR_ALERT | ERR_FATAL;
5479 goto out;
5480 } else {
5481 struct tcpcheck_rule *tcpcheck;
5482 char *err = NULL;
5483
5484 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5485
5486 tcpcheck->action = TCPCHK_ACT_SEND;
5487 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5488 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5489 file, linenum, args[0], args[1], args[2], err);
5490 err_code |= ERR_ALERT | ERR_FATAL;
5491 goto out;
5492 }
5493 tcpcheck->expect_regex = NULL;
5494
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005495 /* comment for this tcpcheck line */
5496 if (strcmp(args[3], "comment") == 0) {
5497 if (!*args[4]) {
5498 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5499 file, linenum, args[3]);
5500 err_code |= ERR_ALERT | ERR_FATAL;
5501 goto out;
5502 }
5503 tcpcheck->comment = strdup(args[4]);
5504 }
5505
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005506 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5507 }
5508 }
5509 else if (strcmp(args[1], "expect") == 0) {
5510 const char *ptr_arg;
5511 int cur_arg;
5512 int inverse = 0;
5513
5514 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5515 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5516 err_code |= ERR_ALERT | ERR_FATAL;
5517 goto out;
5518 }
5519
5520 cur_arg = 2;
5521 /* consider exclamation marks, sole or at the beginning of a word */
5522 while (*(ptr_arg = args[cur_arg])) {
5523 while (*ptr_arg == '!') {
5524 inverse = !inverse;
5525 ptr_arg++;
5526 }
5527 if (*ptr_arg)
5528 break;
5529 cur_arg++;
5530 }
5531 /* now ptr_arg points to the beginning of a word past any possible
5532 * exclamation mark, and cur_arg is the argument which holds this word.
5533 */
5534 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005535 struct tcpcheck_rule *tcpcheck;
5536 char *err = NULL;
5537
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005538 if (!*(args[cur_arg + 1])) {
5539 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5540 file, linenum, args[0], args[1], ptr_arg);
5541 err_code |= ERR_ALERT | ERR_FATAL;
5542 goto out;
5543 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005544
5545 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5546
5547 tcpcheck->action = TCPCHK_ACT_EXPECT;
5548 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5549 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5550 file, linenum, args[0], args[1], args[2], err);
5551 err_code |= ERR_ALERT | ERR_FATAL;
5552 goto out;
5553 }
5554 tcpcheck->expect_regex = NULL;
5555 tcpcheck->inverse = inverse;
5556
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005557 /* tcpcheck comment */
5558 cur_arg += 2;
5559 if (strcmp(args[cur_arg], "comment") == 0) {
5560 if (!*args[cur_arg + 1]) {
5561 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5562 file, linenum, args[cur_arg + 1]);
5563 err_code |= ERR_ALERT | ERR_FATAL;
5564 goto out;
5565 }
5566 tcpcheck->comment = strdup(args[cur_arg + 1]);
5567 }
5568
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005569 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5570 }
5571 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005572 struct tcpcheck_rule *tcpcheck;
5573
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005574 if (!*(args[cur_arg + 1])) {
5575 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5576 file, linenum, args[0], args[1], ptr_arg);
5577 err_code |= ERR_ALERT | ERR_FATAL;
5578 goto out;
5579 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005580
5581 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5582
5583 tcpcheck->action = TCPCHK_ACT_EXPECT;
5584 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5585 tcpcheck->string = strdup(args[cur_arg + 1]);
5586 tcpcheck->expect_regex = NULL;
5587 tcpcheck->inverse = inverse;
5588
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005589 /* tcpcheck comment */
5590 cur_arg += 2;
5591 if (strcmp(args[cur_arg], "comment") == 0) {
5592 if (!*args[cur_arg + 1]) {
5593 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5594 file, linenum, args[cur_arg + 1]);
5595 err_code |= ERR_ALERT | ERR_FATAL;
5596 goto out;
5597 }
5598 tcpcheck->comment = strdup(args[cur_arg + 1]);
5599 }
5600
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005601 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5602 }
5603 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005604 struct tcpcheck_rule *tcpcheck;
5605
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005606 if (!*(args[cur_arg + 1])) {
5607 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5608 file, linenum, args[0], args[1], ptr_arg);
5609 err_code |= ERR_ALERT | ERR_FATAL;
5610 goto out;
5611 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005612
5613 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5614
5615 tcpcheck->action = TCPCHK_ACT_EXPECT;
5616 tcpcheck->string_len = 0;
5617 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005618 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5619 error = NULL;
5620 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5621 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5622 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5623 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005624 err_code |= ERR_ALERT | ERR_FATAL;
5625 goto out;
5626 }
5627 tcpcheck->inverse = inverse;
5628
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005629 /* tcpcheck comment */
5630 cur_arg += 2;
5631 if (strcmp(args[cur_arg], "comment") == 0) {
5632 if (!*args[cur_arg + 1]) {
5633 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5634 file, linenum, args[cur_arg + 1]);
5635 err_code |= ERR_ALERT | ERR_FATAL;
5636 goto out;
5637 }
5638 tcpcheck->comment = strdup(args[cur_arg + 1]);
5639 }
5640
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005641 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5642 }
5643 else {
5644 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5645 file, linenum, args[0], args[1], ptr_arg);
5646 err_code |= ERR_ALERT | ERR_FATAL;
5647 goto out;
5648 }
5649 }
5650 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005651 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005652 err_code |= ERR_ALERT | ERR_FATAL;
5653 goto out;
5654 }
5655 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005656 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005657 if (curproxy == &defproxy) {
5658 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005659 err_code |= ERR_ALERT | ERR_FATAL;
5660 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005661 }
5662
Willy Tarreaub80c2302007-11-30 20:51:32 +01005663 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005664 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005665
5666 if (strcmp(args[1], "fail") == 0) {
5667 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005668 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005669 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5670 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005671 err_code |= ERR_ALERT | ERR_FATAL;
5672 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005673 }
5674
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005675 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5676 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5677 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005678 err_code |= ERR_ALERT | ERR_FATAL;
5679 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005680 }
5681 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5682 }
5683 else {
5684 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005685 err_code |= ERR_ALERT | ERR_FATAL;
5686 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005687 }
5688 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005689#ifdef TPROXY
5690 else if (!strcmp(args[0], "transparent")) {
5691 /* enable transparent proxy connections */
5692 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005693 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5694 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005695 }
5696#endif
5697 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005698 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005699 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005700
Willy Tarreaubaaee002006-06-26 02:48:02 +02005701 if (*(args[1]) == 0) {
5702 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005703 err_code |= ERR_ALERT | ERR_FATAL;
5704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705 }
5706 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005707 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5708 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005709 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005710 else if (!strcmp(args[0], "backlog")) { /* backlog */
5711 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005712 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005713
5714 if (*(args[1]) == 0) {
5715 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005716 err_code |= ERR_ALERT | ERR_FATAL;
5717 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005718 }
5719 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005720 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5721 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005722 }
Willy Tarreau86034312006-12-29 00:10:33 +01005723 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005724 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005725 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005726
Willy Tarreau86034312006-12-29 00:10:33 +01005727 if (*(args[1]) == 0) {
5728 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005729 err_code |= ERR_ALERT | ERR_FATAL;
5730 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005731 }
5732 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005733 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5734 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005735 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005736 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5737 if (*(args[1]) == 0) {
5738 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005739 err_code |= ERR_ALERT | ERR_FATAL;
5740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005741 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005742 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5743 if (err) {
5744 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5745 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005746 err_code |= ERR_ALERT | ERR_FATAL;
5747 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005748 }
5749 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005750 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005752 }
5753 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005754 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005755 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005756 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005757
Willy Tarreaubaaee002006-06-26 02:48:02 +02005758 if (curproxy == &defproxy) {
5759 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005760 err_code |= ERR_ALERT | ERR_FATAL;
5761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005762 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005763 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005764 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005765
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005766 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005767 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005768 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005769 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005770 goto out;
5771 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005772
5773 proto = protocol_by_family(sk->ss_family);
5774 if (!proto || !proto->connect) {
5775 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5776 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005777 err_code |= ERR_ALERT | ERR_FATAL;
5778 goto out;
5779 }
5780
5781 if (port1 != port2) {
5782 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5783 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005784 err_code |= ERR_ALERT | ERR_FATAL;
5785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005786 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005787
5788 if (!port1) {
5789 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5790 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005791 err_code |= ERR_ALERT | ERR_FATAL;
5792 goto out;
5793 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005794
William Lallemanddf1425a2015-04-28 20:17:49 +02005795 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5796 goto out;
5797
Willy Tarreaud5191e72010-02-09 20:50:45 +01005798 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005799 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005800 }
5801 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005802 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005803 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005804
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005805 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5806 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005807 err_code |= ERR_ALERT | ERR_FATAL;
5808 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005809 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005810 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005811 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005812 /**
5813 * The syntax for hash-type config element is
5814 * hash-type {map-based|consistent} [[<algo>] avalanche]
5815 *
5816 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5817 */
5818 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005819
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005820 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5821 err_code |= ERR_WARN;
5822
5823 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005824 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5825 }
5826 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005827 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5828 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005829 else if (strcmp(args[1], "avalanche") == 0) {
5830 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]);
5831 err_code |= ERR_ALERT | ERR_FATAL;
5832 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005833 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005834 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005835 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005836 err_code |= ERR_ALERT | ERR_FATAL;
5837 goto out;
5838 }
Bhaskar98634f02013-10-29 23:30:51 -04005839
5840 /* set the hash function to use */
5841 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005842 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005843 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005844
5845 /* if consistent with no argument, then avalanche modifier is also applied */
5846 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5847 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005848 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005849 /* set the hash function */
5850 if (!strcmp(args[2], "sdbm")) {
5851 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5852 }
5853 else if (!strcmp(args[2], "djb2")) {
5854 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005855 }
5856 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005857 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005858 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005859 else if (!strcmp(args[2], "crc32")) {
5860 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5861 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005862 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005863 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 -05005864 err_code |= ERR_ALERT | ERR_FATAL;
5865 goto out;
5866 }
5867
5868 /* set the hash modifier */
5869 if (!strcmp(args[3], "avalanche")) {
5870 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5871 }
5872 else if (*args[3]) {
5873 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5874 err_code |= ERR_ALERT | ERR_FATAL;
5875 goto out;
5876 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005877 }
William Lallemanda73203e2012-03-12 12:48:57 +01005878 }
William Lallemanda73203e2012-03-12 12:48:57 +01005879 else if (strcmp(args[0], "unique-id-format") == 0) {
5880 if (!*(args[1])) {
5881 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5882 err_code |= ERR_ALERT | ERR_FATAL;
5883 goto out;
5884 }
William Lallemand3203ff42012-11-11 17:30:56 +01005885 if (*(args[2])) {
5886 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5887 err_code |= ERR_ALERT | ERR_FATAL;
5888 goto out;
5889 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005890 free(curproxy->conf.uniqueid_format_string);
5891 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005892
Willy Tarreau62a61232013-04-12 18:13:46 +02005893 free(curproxy->conf.uif_file);
5894 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5895 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005896 }
William Lallemanda73203e2012-03-12 12:48:57 +01005897
5898 else if (strcmp(args[0], "unique-id-header") == 0) {
5899 if (!*(args[1])) {
5900 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5901 err_code |= ERR_ALERT | ERR_FATAL;
5902 goto out;
5903 }
5904 free(curproxy->header_unique_id);
5905 curproxy->header_unique_id = strdup(args[1]);
5906 }
5907
William Lallemand723b73a2012-02-08 16:37:49 +01005908 else if (strcmp(args[0], "log-format") == 0) {
5909 if (!*(args[1])) {
5910 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5911 err_code |= ERR_ALERT | ERR_FATAL;
5912 goto out;
5913 }
William Lallemand3203ff42012-11-11 17:30:56 +01005914 if (*(args[2])) {
5915 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5916 err_code |= ERR_ALERT | ERR_FATAL;
5917 goto out;
5918 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005919
Willy Tarreau62a61232013-04-12 18:13:46 +02005920 if (curproxy->conf.logformat_string != default_http_log_format &&
5921 curproxy->conf.logformat_string != default_tcp_log_format &&
5922 curproxy->conf.logformat_string != clf_http_log_format)
5923 free(curproxy->conf.logformat_string);
5924 curproxy->conf.logformat_string = strdup(args[1]);
5925
5926 free(curproxy->conf.lfs_file);
5927 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5928 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005929
5930 /* get a chance to improve log-format error reporting by
5931 * reporting the correct line-number when possible.
5932 */
5933 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5934 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5935 file, linenum, curproxy->id);
5936 err_code |= ERR_WARN;
5937 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005938 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005939 else if (!strcmp(args[0], "log-format-sd")) {
5940 if (!*(args[1])) {
5941 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5942 err_code |= ERR_ALERT | ERR_FATAL;
5943 goto out;
5944 }
5945 if (*(args[2])) {
5946 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5947 err_code |= ERR_ALERT | ERR_FATAL;
5948 goto out;
5949 }
5950
5951 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5952 free(curproxy->conf.logformat_sd_string);
5953 curproxy->conf.logformat_sd_string = strdup(args[1]);
5954
5955 free(curproxy->conf.lfsd_file);
5956 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5957 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5958
5959 /* get a chance to improve log-format-sd error reporting by
5960 * reporting the correct line-number when possible.
5961 */
5962 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5963 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5964 file, linenum, curproxy->id);
5965 err_code |= ERR_WARN;
5966 }
5967 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005968 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5969 if (*(args[1]) == 0) {
5970 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5971 err_code |= ERR_ALERT | ERR_FATAL;
5972 goto out;
5973 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005974 chunk_destroy(&curproxy->log_tag);
5975 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005976 }
William Lallemand0f99e342011-10-12 17:50:54 +02005977 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5978 /* delete previous herited or defined syslog servers */
5979 struct logsrv *back;
5980
5981 if (*(args[1]) != 0) {
5982 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5983 err_code |= ERR_ALERT | ERR_FATAL;
5984 goto out;
5985 }
5986
William Lallemand723b73a2012-02-08 16:37:49 +01005987 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5988 LIST_DEL(&tmplogsrv->list);
5989 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005990 }
5991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005992 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005993 struct logsrv *logsrv;
5994
Willy Tarreaubaaee002006-06-26 02:48:02 +02005995 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005996 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005997 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005998 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005999 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006000 LIST_INIT(&node->list);
6001 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6002 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006003 }
6004 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006005 struct sockaddr_storage *sk;
6006 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006007 int arg = 0;
6008 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006009
6010 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006011
Willy Tarreau18324f52014-06-27 18:10:07 +02006012 /* just after the address, a length may be specified */
6013 if (strcmp(args[arg+2], "len") == 0) {
6014 len = atoi(args[arg+3]);
6015 if (len < 80 || len > 65535) {
6016 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6017 file, linenum, args[arg+3]);
6018 err_code |= ERR_ALERT | ERR_FATAL;
6019 goto out;
6020 }
6021 logsrv->maxlen = len;
6022
6023 /* skip these two args */
6024 arg += 2;
6025 }
6026 else
6027 logsrv->maxlen = MAX_SYSLOG_LEN;
6028
6029 if (logsrv->maxlen > global.max_syslog_len) {
6030 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02006031 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02006032 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006033 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006034 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006035 }
6036
Dragan Dosen1322d092015-09-22 16:05:32 +02006037 /* after the length, a format may be specified */
6038 if (strcmp(args[arg+2], "format") == 0) {
6039 logsrv->format = get_log_format(args[arg+3]);
6040 if (logsrv->format < 0) {
6041 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6042 err_code |= ERR_ALERT | ERR_FATAL;
6043 goto out;
6044 }
6045
6046 /* skip these two args */
6047 arg += 2;
6048 }
6049
William Lallemanddf1425a2015-04-28 20:17:49 +02006050 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6051 goto out;
6052
Willy Tarreau18324f52014-06-27 18:10:07 +02006053 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006054 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006055 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006056 err_code |= ERR_ALERT | ERR_FATAL;
6057 goto out;
6058
Willy Tarreaubaaee002006-06-26 02:48:02 +02006059 }
6060
William Lallemand0f99e342011-10-12 17:50:54 +02006061 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006062 if (*(args[arg+3])) {
6063 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006064 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006065 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006066 err_code |= ERR_ALERT | ERR_FATAL;
6067 goto out;
6068
Willy Tarreaubaaee002006-06-26 02:48:02 +02006069 }
6070 }
6071
William Lallemand0f99e342011-10-12 17:50:54 +02006072 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006073 if (*(args[arg+4])) {
6074 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006075 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006076 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006077 err_code |= ERR_ALERT | ERR_FATAL;
6078 goto out;
6079
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006080 }
6081 }
6082
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006083 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006084 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006085 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006086 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006087 goto out;
6088 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006089
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006090 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006091
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006092 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006093 if (port1 != port2) {
6094 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6095 file, linenum, args[0], args[1]);
6096 err_code |= ERR_ALERT | ERR_FATAL;
6097 goto out;
6098 }
6099
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006100 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006101 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006102 }
William Lallemand0f99e342011-10-12 17:50:54 +02006103
6104 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006105 }
6106 else {
6107 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6108 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006109 err_code |= ERR_ALERT | ERR_FATAL;
6110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006111 }
6112 }
6113 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006114 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006115 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006116 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006117 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006118
Willy Tarreau977b8e42006-12-29 14:19:17 +01006119 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006120 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006121
Willy Tarreaubaaee002006-06-26 02:48:02 +02006122 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006123 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6124 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006125 err_code |= ERR_ALERT | ERR_FATAL;
6126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006127 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006128
6129 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006130 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6131 free(curproxy->conn_src.iface_name);
6132 curproxy->conn_src.iface_name = NULL;
6133 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006134
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006135 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006136 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006137 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006138 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006139 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006140 goto out;
6141 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006142
6143 proto = protocol_by_family(sk->ss_family);
6144 if (!proto || !proto->connect) {
6145 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006146 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006147 err_code |= ERR_ALERT | ERR_FATAL;
6148 goto out;
6149 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006150
6151 if (port1 != port2) {
6152 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6153 file, linenum, args[0], args[1]);
6154 err_code |= ERR_ALERT | ERR_FATAL;
6155 goto out;
6156 }
6157
Willy Tarreauef9a3602012-12-08 22:29:20 +01006158 curproxy->conn_src.source_addr = *sk;
6159 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006160
6161 cur_arg = 2;
6162 while (*(args[cur_arg])) {
6163 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006164#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006165 if (!*args[cur_arg + 1]) {
6166 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6167 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006168 err_code |= ERR_ALERT | ERR_FATAL;
6169 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006170 }
6171
6172 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006173 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6174 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006175 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006176 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6177 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006178 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6179 char *name, *end;
6180
6181 name = args[cur_arg+1] + 7;
6182 while (isspace(*name))
6183 name++;
6184
6185 end = name;
6186 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6187 end++;
6188
Willy Tarreauef9a3602012-12-08 22:29:20 +01006189 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6190 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6191 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6192 curproxy->conn_src.bind_hdr_len = end - name;
6193 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6194 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6195 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006196
6197 /* now look for an occurrence number */
6198 while (isspace(*end))
6199 end++;
6200 if (*end == ',') {
6201 end++;
6202 name = end;
6203 if (*end == '-')
6204 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006205 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006206 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006207 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006208 }
6209
Willy Tarreauef9a3602012-12-08 22:29:20 +01006210 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006211 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6212 " occurrences values smaller than %d.\n",
6213 file, linenum, MAX_HDR_HISTORY);
6214 err_code |= ERR_ALERT | ERR_FATAL;
6215 goto out;
6216 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006217 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006218 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006219
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006220 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006221 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006222 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006223 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006224 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006225 goto out;
6226 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006227
6228 proto = protocol_by_family(sk->ss_family);
6229 if (!proto || !proto->connect) {
6230 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6231 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006232 err_code |= ERR_ALERT | ERR_FATAL;
6233 goto out;
6234 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006235
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006236 if (port1 != port2) {
6237 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6238 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006239 err_code |= ERR_ALERT | ERR_FATAL;
6240 goto out;
6241 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006242 curproxy->conn_src.tproxy_addr = *sk;
6243 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006244 }
6245 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006246#else /* no TPROXY support */
6247 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006248 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006249 err_code |= ERR_ALERT | ERR_FATAL;
6250 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006251#endif
6252 cur_arg += 2;
6253 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006254 }
6255
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006256 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6257#ifdef SO_BINDTODEVICE
6258 if (!*args[cur_arg + 1]) {
6259 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6260 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006261 err_code |= ERR_ALERT | ERR_FATAL;
6262 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006263 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006264 free(curproxy->conn_src.iface_name);
6265 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6266 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006267 global.last_checks |= LSTCHK_NETADM;
6268#else
6269 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6270 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006271 err_code |= ERR_ALERT | ERR_FATAL;
6272 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006273#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006274 cur_arg += 2;
6275 continue;
6276 }
6277 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006278 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006279 err_code |= ERR_ALERT | ERR_FATAL;
6280 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006281 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006282 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006283 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6284 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6285 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006286 err_code |= ERR_ALERT | ERR_FATAL;
6287 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006289 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006290 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006291 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6292 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006293 err_code |= ERR_ALERT | ERR_FATAL;
6294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006295 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006296
6297 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006298 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006299 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006300 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006302 }
6303 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006304 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006305 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006306 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006307 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006308 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006309 }
6310 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006311 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006312 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006313 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006314 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006316 }
6317 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006318 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006319 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006320 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006321 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006323 }
6324 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006325 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006326 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006327 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006328 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006330 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006331 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006332 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006333 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006334 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006335 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006336 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006337 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006338 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006339 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006340 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6341 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006342 err_code |= ERR_ALERT | ERR_FATAL;
6343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006344 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006345
6346 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006347 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006348 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006349 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006351 }
6352 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006353 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006354 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006355 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006356 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006358 }
6359 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006360 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006361 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006362 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006363 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006365 }
6366 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006367 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006368 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006369 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006370 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006372 }
6373 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006374 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006375 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006376 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006377 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006379 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006380 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006381 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006382 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006383 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006384 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006385 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006386 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006387 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006388 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006389
Willy Tarreaubaaee002006-06-26 02:48:02 +02006390 if (curproxy == &defproxy) {
6391 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006392 err_code |= ERR_ALERT | ERR_FATAL;
6393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006394 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006395 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006396 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006397
Willy Tarreaubaaee002006-06-26 02:48:02 +02006398 if (*(args[1]) == 0) {
6399 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006400 err_code |= ERR_ALERT | ERR_FATAL;
6401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006402 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006403
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006404 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006405 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6406 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6407 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006408 err_code |= ERR_ALERT | ERR_FATAL;
6409 goto out;
6410 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006411 err_code |= warnif_cond_conflicts(cond,
6412 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6413 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006414 }
6415 else if (*args[2]) {
6416 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6417 file, linenum, args[0], args[2]);
6418 err_code |= ERR_ALERT | ERR_FATAL;
6419 goto out;
6420 }
6421
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006422 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006423 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006424 wl->s = strdup(args[1]);
6425 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006426 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006427 }
6428 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006429 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006430 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6431 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006432 err_code |= ERR_ALERT | ERR_FATAL;
6433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006434 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006435
Willy Tarreauade5ec42010-01-28 19:33:49 +01006436 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006437 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006438 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006439 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006441 }
6442 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006443 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006444 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006445 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006446 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006448 }
6449 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006450 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006451 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006452 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006453 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006455 }
6456 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006457 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006458 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6459 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006460 err_code |= ERR_ALERT | ERR_FATAL;
6461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006462 }
6463
Willy Tarreauade5ec42010-01-28 19:33:49 +01006464 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006465 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006466 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006467 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006469 }
6470 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006471 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006472 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006473 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006474 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006476 }
6477 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006478 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006479 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006480 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006481 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006483 }
6484 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006485 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006486
Willy Tarreaubaaee002006-06-26 02:48:02 +02006487 if (curproxy == &defproxy) {
6488 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006489 err_code |= ERR_ALERT | ERR_FATAL;
6490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006491 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006492 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006493 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006494
Willy Tarreaubaaee002006-06-26 02:48:02 +02006495 if (*(args[1]) == 0) {
6496 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006497 err_code |= ERR_ALERT | ERR_FATAL;
6498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006499 }
6500
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006501 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006502 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6503 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6504 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006505 err_code |= ERR_ALERT | ERR_FATAL;
6506 goto out;
6507 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006508 err_code |= warnif_cond_conflicts(cond,
6509 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6510 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006511 }
6512 else if (*args[2]) {
6513 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6514 file, linenum, args[0], args[2]);
6515 err_code |= ERR_ALERT | ERR_FATAL;
6516 goto out;
6517 }
6518
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006519 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006520 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006521 wl->s = strdup(args[1]);
6522 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006523 }
6524 else if (!strcmp(args[0], "errorloc") ||
6525 !strcmp(args[0], "errorloc302") ||
6526 !strcmp(args[0], "errorloc303")) { /* error location */
6527 int errnum, errlen;
6528 char *err;
6529
Willy Tarreau977b8e42006-12-29 14:19:17 +01006530 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006531 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006532
Willy Tarreaubaaee002006-06-26 02:48:02 +02006533 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006534 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006535 err_code |= ERR_ALERT | ERR_FATAL;
6536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006537 }
6538
6539 errnum = atol(args[1]);
6540 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006541 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6542 err = malloc(errlen);
6543 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006544 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006545 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6546 err = malloc(errlen);
6547 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006548 }
6549
Willy Tarreau0f772532006-12-23 20:51:41 +01006550 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6551 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006552 chunk_destroy(&curproxy->errmsg[rc]);
6553 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006554 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006555 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006556 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006557
6558 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006559 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6560 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006561 free(err);
6562 }
6563 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006564 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6565 int errnum, errlen, fd;
6566 char *err;
6567 struct stat stat;
6568
6569 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006570 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006571
6572 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006573 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006574 err_code |= ERR_ALERT | ERR_FATAL;
6575 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006576 }
6577
6578 fd = open(args[2], O_RDONLY);
6579 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6580 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6581 file, linenum, args[2], args[1]);
6582 if (fd >= 0)
6583 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006584 err_code |= ERR_ALERT | ERR_FATAL;
6585 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006586 }
6587
Willy Tarreau27a674e2009-08-17 07:23:33 +02006588 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006589 errlen = stat.st_size;
6590 } else {
6591 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006592 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006593 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006594 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006595 }
6596
6597 err = malloc(errlen); /* malloc() must succeed during parsing */
6598 errnum = read(fd, err, errlen);
6599 if (errnum != errlen) {
6600 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6601 file, linenum, args[2], args[1]);
6602 close(fd);
6603 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006604 err_code |= ERR_ALERT | ERR_FATAL;
6605 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006606 }
6607 close(fd);
6608
6609 errnum = atol(args[1]);
6610 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6611 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006612 chunk_destroy(&curproxy->errmsg[rc]);
6613 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006614 break;
6615 }
6616 }
6617
6618 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006619 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6620 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006621 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006622 free(err);
6623 }
6624 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006625 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006626 struct cfg_kw_list *kwl;
6627 int index;
6628
6629 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6630 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6631 if (kwl->kw[index].section != CFG_LISTEN)
6632 continue;
6633 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6634 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006635 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006636 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006637 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006638 err_code |= ERR_ALERT | ERR_FATAL;
6639 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006640 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006641 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006642 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006643 err_code |= ERR_WARN;
6644 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006645 }
Willy Tarreau93893792009-07-23 13:19:11 +02006646 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006647 }
6648 }
6649 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006650
Willy Tarreau6daf3432008-01-22 16:44:08 +01006651 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006652 err_code |= ERR_ALERT | ERR_FATAL;
6653 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006654 }
Willy Tarreau93893792009-07-23 13:19:11 +02006655 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006656 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006657 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006658}
6659
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006660int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006661cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6662{
6663#ifdef CONFIG_HAP_NS
6664 const char *err;
6665 const char *item = args[0];
6666
6667 if (!strcmp(item, "namespace_list")) {
6668 return 0;
6669 }
6670 else if (!strcmp(item, "namespace")) {
6671 size_t idx = 1;
6672 const char *current;
6673 while (*(current = args[idx++])) {
6674 err = invalid_char(current);
6675 if (err) {
6676 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6677 file, linenum, *err, item, current);
6678 return ERR_ALERT | ERR_FATAL;
6679 }
6680
6681 if (netns_store_lookup(current, strlen(current))) {
6682 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6683 file, linenum, current);
6684 return ERR_ALERT | ERR_FATAL;
6685 }
6686 if (!netns_store_insert(current)) {
6687 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6688 file, linenum, current);
6689 return ERR_ALERT | ERR_FATAL;
6690 }
6691 }
6692 }
6693
6694 return 0;
6695#else
6696 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6697 file, linenum);
6698 return ERR_ALERT | ERR_FATAL;
6699#endif
6700}
6701
6702int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006703cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6704{
6705
6706 int err_code = 0;
6707 const char *err;
6708
6709 if (!strcmp(args[0], "userlist")) { /* new userlist */
6710 struct userlist *newul;
6711
6712 if (!*args[1]) {
6713 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6714 file, linenum, args[0]);
6715 err_code |= ERR_ALERT | ERR_FATAL;
6716 goto out;
6717 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006718 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6719 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006720
6721 err = invalid_char(args[1]);
6722 if (err) {
6723 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6724 file, linenum, *err, args[0], args[1]);
6725 err_code |= ERR_ALERT | ERR_FATAL;
6726 goto out;
6727 }
6728
6729 for (newul = userlist; newul; newul = newul->next)
6730 if (!strcmp(newul->name, args[1])) {
6731 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6732 file, linenum, args[1]);
6733 err_code |= ERR_WARN;
6734 goto out;
6735 }
6736
6737 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6738 if (!newul) {
6739 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6740 err_code |= ERR_ALERT | ERR_ABORT;
6741 goto out;
6742 }
6743
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006744 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006745 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006746 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6747 err_code |= ERR_ALERT | ERR_ABORT;
6748 goto out;
6749 }
6750
6751 newul->next = userlist;
6752 userlist = newul;
6753
6754 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006755 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006756 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006757 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006758
6759 if (!*args[1]) {
6760 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6761 file, linenum, args[0]);
6762 err_code |= ERR_ALERT | ERR_FATAL;
6763 goto out;
6764 }
6765
6766 err = invalid_char(args[1]);
6767 if (err) {
6768 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6769 file, linenum, *err, args[0], args[1]);
6770 err_code |= ERR_ALERT | ERR_FATAL;
6771 goto out;
6772 }
6773
William Lallemand4ac9f542015-05-28 18:03:51 +02006774 if (!userlist)
6775 goto out;
6776
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006777 for (ag = userlist->groups; ag; ag = ag->next)
6778 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006779 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6780 file, linenum, args[1], userlist->name);
6781 err_code |= ERR_ALERT;
6782 goto out;
6783 }
6784
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006785 ag = calloc(1, sizeof(*ag));
6786 if (!ag) {
6787 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6788 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006789 goto out;
6790 }
6791
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006792 ag->name = strdup(args[1]);
6793 if (!ag) {
6794 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6795 err_code |= ERR_ALERT | ERR_ABORT;
6796 goto out;
6797 }
6798
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006799 cur_arg = 2;
6800
6801 while (*args[cur_arg]) {
6802 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006803 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006804 cur_arg += 2;
6805 continue;
6806 } else {
6807 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6808 file, linenum, args[0]);
6809 err_code |= ERR_ALERT | ERR_FATAL;
6810 goto out;
6811 }
6812 }
6813
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006814 ag->next = userlist->groups;
6815 userlist->groups = ag;
6816
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006817 } else if (!strcmp(args[0], "user")) { /* new user */
6818 struct auth_users *newuser;
6819 int cur_arg;
6820
6821 if (!*args[1]) {
6822 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6823 file, linenum, args[0]);
6824 err_code |= ERR_ALERT | ERR_FATAL;
6825 goto out;
6826 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006827 if (!userlist)
6828 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006829
6830 for (newuser = userlist->users; newuser; newuser = newuser->next)
6831 if (!strcmp(newuser->user, args[1])) {
6832 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6833 file, linenum, args[1], userlist->name);
6834 err_code |= ERR_ALERT;
6835 goto out;
6836 }
6837
6838 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6839 if (!newuser) {
6840 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6841 err_code |= ERR_ALERT | ERR_ABORT;
6842 goto out;
6843 }
6844
6845 newuser->user = strdup(args[1]);
6846
6847 newuser->next = userlist->users;
6848 userlist->users = newuser;
6849
6850 cur_arg = 2;
6851
6852 while (*args[cur_arg]) {
6853 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006854#ifdef CONFIG_HAP_CRYPT
6855 if (!crypt("", args[cur_arg + 1])) {
6856 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6857 file, linenum, newuser->user);
6858 err_code |= ERR_ALERT | ERR_FATAL;
6859 goto out;
6860 }
6861#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006862 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6863 file, linenum);
6864 err_code |= ERR_ALERT;
6865#endif
6866 newuser->pass = strdup(args[cur_arg + 1]);
6867 cur_arg += 2;
6868 continue;
6869 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6870 newuser->pass = strdup(args[cur_arg + 1]);
6871 newuser->flags |= AU_O_INSECURE;
6872 cur_arg += 2;
6873 continue;
6874 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006875 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006876 cur_arg += 2;
6877 continue;
6878 } else {
6879 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6880 file, linenum, args[0]);
6881 err_code |= ERR_ALERT | ERR_FATAL;
6882 goto out;
6883 }
6884 }
6885 } else {
6886 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6887 err_code |= ERR_ALERT | ERR_FATAL;
6888 }
6889
6890out:
6891 return err_code;
6892}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006893
6894/*
6895 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006896 * Returns the error code, 0 if OK, or any combination of :
6897 * - ERR_ABORT: must abort ASAP
6898 * - ERR_FATAL: we can continue parsing but not start the service
6899 * - ERR_WARN: a warning has been emitted
6900 * - ERR_ALERT: an alert has been emitted
6901 * Only the two first ones can stop processing, the two others are just
6902 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006903 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006904int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006905{
William Lallemand64e84512015-05-12 14:25:37 +02006906 char *thisline;
6907 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006908 FILE *f;
6909 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006910 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006911 struct cfg_section *cs = NULL;
6912 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006913 int readbytes = 0;
6914
6915 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006916 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006917 return -1;
6918 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006919
6920 /* Register internal sections */
6921 if (!cfg_register_section("listen", cfg_parse_listen) ||
6922 !cfg_register_section("frontend", cfg_parse_listen) ||
6923 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006924 !cfg_register_section("defaults", cfg_parse_listen) ||
6925 !cfg_register_section("global", cfg_parse_global) ||
6926 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006927 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006928 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006929 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6930 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006931 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006932
Willy Tarreaubaaee002006-06-26 02:48:02 +02006933 if ((f=fopen(file,"r")) == NULL)
6934 return -1;
6935
William Lallemandb2f07452015-05-12 14:27:13 +02006936next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006937 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006938 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006939 char *end;
6940 char *args[MAX_LINE_ARGS + 1];
6941 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006942 int dquote = 0; /* double quote */
6943 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006944
Willy Tarreaubaaee002006-06-26 02:48:02 +02006945 linenum++;
6946
6947 end = line + strlen(line);
6948
William Lallemand64e84512015-05-12 14:25:37 +02006949 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006950 /* Check if we reached the limit and the last char is not \n.
6951 * Watch out for the last line without the terminating '\n'!
6952 */
William Lallemand64e84512015-05-12 14:25:37 +02006953 char *newline;
6954 int newlinesize = linesize * 2;
6955
6956 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6957 if (newline == NULL) {
6958 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6959 file, linenum);
6960 err_code |= ERR_ALERT | ERR_FATAL;
6961 continue;
6962 }
6963
6964 readbytes = linesize - 1;
6965 linesize = newlinesize;
6966 thisline = newline;
6967 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006968 }
6969
William Lallemand64e84512015-05-12 14:25:37 +02006970 readbytes = 0;
6971
Willy Tarreaubaaee002006-06-26 02:48:02 +02006972 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006973 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006974 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006975
Willy Tarreaubaaee002006-06-26 02:48:02 +02006976 arg = 0;
6977 args[arg] = line;
6978
6979 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006980 if (*line == '"' && !squote) { /* double quote outside single quotes */
6981 if (dquote)
6982 dquote = 0;
6983 else
6984 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006985 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006986 end--;
6987 }
6988 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6989 if (squote)
6990 squote = 0;
6991 else
6992 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006993 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006994 end--;
6995 }
6996 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006997 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6998 * C equivalent value. Other combinations left unchanged (eg: \1).
6999 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007000 int skip = 0;
7001 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7002 *line = line[1];
7003 skip = 1;
7004 }
7005 else if (line[1] == 'r') {
7006 *line = '\r';
7007 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007008 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007009 else if (line[1] == 'n') {
7010 *line = '\n';
7011 skip = 1;
7012 }
7013 else if (line[1] == 't') {
7014 *line = '\t';
7015 skip = 1;
7016 }
7017 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007018 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007019 unsigned char hex1, hex2;
7020 hex1 = toupper(line[2]) - '0';
7021 hex2 = toupper(line[3]) - '0';
7022 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7023 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7024 *line = (hex1<<4) + hex2;
7025 skip = 3;
7026 }
7027 else {
7028 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007029 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007030 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007031 } else if (line[1] == '"') {
7032 *line = '"';
7033 skip = 1;
7034 } else if (line[1] == '\'') {
7035 *line = '\'';
7036 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007037 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7038 *line = '$';
7039 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007040 }
7041 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007042 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007043 end -= skip;
7044 }
7045 line++;
7046 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007047 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007048 /* end of string, end of loop */
7049 *line = 0;
7050 break;
7051 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007052 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007053 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007054 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007055 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007056 line++;
7057 args[++arg] = line;
7058 }
William Lallemandb2f07452015-05-12 14:27:13 +02007059 else if (dquote && *line == '$') {
7060 /* environment variables are evaluated inside double quotes */
7061 char *var_beg;
7062 char *var_end;
7063 char save_char;
7064 char *value;
7065 int val_len;
7066 int newlinesize;
7067 int braces = 0;
7068
7069 var_beg = line + 1;
7070 var_end = var_beg;
7071
7072 if (*var_beg == '{') {
7073 var_beg++;
7074 var_end++;
7075 braces = 1;
7076 }
7077
7078 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7079 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7080 err_code |= ERR_ALERT | ERR_FATAL;
7081 goto next_line; /* skip current line */
7082 }
7083
7084 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7085 var_end++;
7086
7087 save_char = *var_end;
7088 *var_end = '\0';
7089 value = getenv(var_beg);
7090 *var_end = save_char;
7091 val_len = value ? strlen(value) : 0;
7092
7093 if (braces) {
7094 if (*var_end == '}') {
7095 var_end++;
7096 braces = 0;
7097 } else {
7098 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7099 err_code |= ERR_ALERT | ERR_FATAL;
7100 goto next_line; /* skip current line */
7101 }
7102 }
7103
7104 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7105
7106 /* if not enough space in thisline */
7107 if (newlinesize > linesize) {
7108 char *newline;
7109
7110 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7111 if (newline == NULL) {
7112 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7113 err_code |= ERR_ALERT | ERR_FATAL;
7114 goto next_line; /* slip current line */
7115 }
7116 /* recompute pointers if realloc returns a new pointer */
7117 if (newline != thisline) {
7118 int i;
7119 int diff;
7120
7121 for (i = 0; i <= arg; i++) {
7122 diff = args[i] - thisline;
7123 args[i] = newline + diff;
7124 }
7125
7126 diff = var_end - thisline;
7127 var_end = newline + diff;
7128 diff = end - thisline;
7129 end = newline + diff;
7130 diff = line - thisline;
7131 line = newline + diff;
7132 thisline = newline;
7133 }
7134 linesize = newlinesize;
7135 }
7136
7137 /* insert value inside the line */
7138 memmove(line + val_len, var_end, end - var_end + 1);
7139 memcpy(line, value, val_len);
7140 end += val_len - (var_end - line);
7141 line += val_len;
7142 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007143 else {
7144 line++;
7145 }
7146 }
William Lallemandb2f07452015-05-12 14:27:13 +02007147
William Lallemandf9873ba2015-05-05 17:37:14 +02007148 if (dquote) {
7149 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7150 err_code |= ERR_ALERT | ERR_FATAL;
7151 }
7152
7153 if (squote) {
7154 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7155 err_code |= ERR_ALERT | ERR_FATAL;
7156 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007157
7158 /* empty line */
7159 if (!**args)
7160 continue;
7161
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007162 if (*line) {
7163 /* we had to stop due to too many args.
7164 * Let's terminate the string, print the offending part then cut the
7165 * last arg.
7166 */
7167 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7168 line++;
7169 *line = '\0';
7170
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007171 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007172 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007173 err_code |= ERR_ALERT | ERR_FATAL;
7174 args[arg] = line;
7175 }
7176
Willy Tarreau540abe42007-05-02 20:50:16 +02007177 /* zero out remaining args and ensure that at least one entry
7178 * is zeroed out.
7179 */
7180 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007181 args[arg] = line;
7182 }
7183
Willy Tarreau3842f002009-06-14 11:39:52 +02007184 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007185 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007186 char *tmp;
7187
Willy Tarreau3842f002009-06-14 11:39:52 +02007188 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007189 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007190 for (arg=0; *args[arg+1]; arg++)
7191 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007192 *tmp = '\0'; // fix the next arg to \0
7193 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007194 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007195 else if (!strcmp(args[0], "default")) {
7196 kwm = KWM_DEF;
7197 for (arg=0; *args[arg+1]; arg++)
7198 args[arg] = args[arg+1]; // shift args after inversion
7199 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007200
William Lallemand0f99e342011-10-12 17:50:54 +02007201 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7202 strcmp(args[0], "log") != 0) {
7203 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007204 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007205 }
7206
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007207 /* detect section start */
7208 list_for_each_entry(ics, &sections, list) {
7209 if (strcmp(args[0], ics->section_name) == 0) {
7210 cursection = ics->section_name;
7211 cs = ics;
7212 break;
7213 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007214 }
7215
Willy Tarreaubaaee002006-06-26 02:48:02 +02007216 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007217 if (cs)
7218 err_code |= cs->section_parser(file, linenum, args, kwm);
7219 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007220 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007221 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007222 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007223
7224 if (err_code & ERR_ABORT)
7225 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007226 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007227 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007228 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007229 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007230 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007231}
7232
Willy Tarreau64ab6072014-09-16 12:17:36 +02007233/* This function propagates processes from frontend <from> to backend <to> so
7234 * that it is always guaranteed that a backend pointed to by a frontend is
7235 * bound to all of its processes. After that, if the target is a "listen"
7236 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007237 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007238 * checked first to ensure that <to> is already bound to all processes of
7239 * <from>, there is no risk of looping and we ensure to follow the shortest
7240 * path to the destination.
7241 *
7242 * It is possible to set <to> to NULL for the first call so that the function
7243 * takes care of visiting the initial frontend in <from>.
7244 *
7245 * It is important to note that the function relies on the fact that all names
7246 * have already been resolved.
7247 */
7248void propagate_processes(struct proxy *from, struct proxy *to)
7249{
7250 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007251
7252 if (to) {
7253 /* check whether we need to go down */
7254 if (from->bind_proc &&
7255 (from->bind_proc & to->bind_proc) == from->bind_proc)
7256 return;
7257
7258 if (!from->bind_proc && !to->bind_proc)
7259 return;
7260
7261 to->bind_proc = from->bind_proc ?
7262 (to->bind_proc | from->bind_proc) : 0;
7263
7264 /* now propagate down */
7265 from = to;
7266 }
7267
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007268 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007269 return;
7270
Willy Tarreauf6b70012014-12-18 14:00:43 +01007271 if (from->state == PR_STSTOPPED)
7272 return;
7273
Willy Tarreau64ab6072014-09-16 12:17:36 +02007274 /* default_backend */
7275 if (from->defbe.be)
7276 propagate_processes(from, from->defbe.be);
7277
7278 /* use_backend */
7279 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007280 if (rule->dynamic)
7281 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007282 to = rule->be.backend;
7283 propagate_processes(from, to);
7284 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007285}
7286
Willy Tarreaubb925012009-07-23 13:36:36 +02007287/*
7288 * Returns the error code, 0 if OK, or any combination of :
7289 * - ERR_ABORT: must abort ASAP
7290 * - ERR_FATAL: we can continue parsing but not start the service
7291 * - ERR_WARN: a warning has been emitted
7292 * - ERR_ALERT: an alert has been emitted
7293 * Only the two first ones can stop processing, the two others are just
7294 * indicators.
7295 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007296int check_config_validity()
7297{
7298 int cfgerr = 0;
7299 struct proxy *curproxy = NULL;
7300 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007301 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007302 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007303 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007304
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007305 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007306 /*
7307 * Now, check for the integrity of all that we have collected.
7308 */
7309
7310 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007311 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007312
Willy Tarreau193b8c62012-11-22 00:17:38 +01007313 if (!global.tune.max_http_hdr)
7314 global.tune.max_http_hdr = MAX_HTTP_HDR;
7315
7316 if (!global.tune.cookie_len)
7317 global.tune.cookie_len = CAPTURE_LEN;
7318
7319 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7320
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007321 /* Post initialisation of the users and groups lists. */
7322 err_code = userlist_postinit();
7323 if (err_code != ERR_NONE)
7324 goto out;
7325
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007326 /* first, we will invert the proxy list order */
7327 curproxy = NULL;
7328 while (proxy) {
7329 struct proxy *next;
7330
7331 next = proxy->next;
7332 proxy->next = curproxy;
7333 curproxy = proxy;
7334 if (!next)
7335 break;
7336 proxy = next;
7337 }
7338
Willy Tarreau419ead82014-09-16 13:41:21 +02007339 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007340 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007341 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007342 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007343 struct act_rule *trule;
7344 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007345 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007346 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007347 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007348
Willy Tarreau050536d2012-10-04 08:47:34 +02007349 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007350 /* proxy ID not set, use automatic numbering with first
7351 * spare entry starting with next_pxid.
7352 */
7353 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7354 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7355 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007356 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007357 next_pxid++;
7358
Willy Tarreau55ea7572007-06-17 19:56:27 +02007359
Willy Tarreaubaaee002006-06-26 02:48:02 +02007360 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007361 /* ensure we don't keep listeners uselessly bound */
7362 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007363 free((void *)curproxy->table.peers.name);
7364 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007365 continue;
7366 }
7367
Willy Tarreau102df612014-05-07 23:56:38 +02007368 /* Check multi-process mode compatibility for the current proxy */
7369
7370 if (curproxy->bind_proc) {
7371 /* an explicit bind-process was specified, let's check how many
7372 * processes remain.
7373 */
David Carliere6c39412015-07-02 07:00:17 +00007374 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007375
7376 curproxy->bind_proc &= nbits(global.nbproc);
7377 if (!curproxy->bind_proc && nbproc == 1) {
7378 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);
7379 curproxy->bind_proc = 1;
7380 }
7381 else if (!curproxy->bind_proc && nbproc > 1) {
7382 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);
7383 curproxy->bind_proc = 0;
7384 }
7385 }
7386
Willy Tarreau3d209582014-05-09 17:06:11 +02007387 /* check and reduce the bind-proc of each listener */
7388 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7389 unsigned long mask;
7390
7391 if (!bind_conf->bind_proc)
7392 continue;
7393
7394 mask = nbits(global.nbproc);
7395 if (curproxy->bind_proc)
7396 mask &= curproxy->bind_proc;
7397 /* mask cannot be null here thanks to the previous checks */
7398
David Carliere6c39412015-07-02 07:00:17 +00007399 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007400 bind_conf->bind_proc &= mask;
7401
7402 if (!bind_conf->bind_proc && nbproc == 1) {
7403 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",
7404 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7405 bind_conf->bind_proc = mask & ~(mask - 1);
7406 }
7407 else if (!bind_conf->bind_proc && nbproc > 1) {
7408 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",
7409 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7410 bind_conf->bind_proc = 0;
7411 }
7412 }
7413
Willy Tarreauff01a212009-03-15 13:46:16 +01007414 switch (curproxy->mode) {
7415 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007416 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007417 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007418 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7419 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007420 cfgerr++;
7421 }
7422
7423 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007424 Warning("config : servers will be ignored for %s '%s'.\n",
7425 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007426 break;
7427
7428 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007429 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007430 break;
7431
7432 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007433 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007434 break;
7435 }
7436
Willy Tarreauf3934b82015-08-11 11:36:45 +02007437 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7438 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7439 proxy_type_str(curproxy), curproxy->id);
7440 err_code |= ERR_WARN;
7441 }
7442
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007443 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007444 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007445 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007446 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7447 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007448 cfgerr++;
7449 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007450#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007451 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007452 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7453 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007454 cfgerr++;
7455 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007456#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007457 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007458 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7459 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007460 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007461 }
7462 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007463 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007464 /* If no LB algo is set in a backend, and we're not in
7465 * transparent mode, dispatch mode nor proxy mode, we
7466 * want to use balance roundrobin by default.
7467 */
7468 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7469 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007470 }
7471 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007472
Willy Tarreau1620ec32011-08-06 17:05:02 +02007473 if (curproxy->options & PR_O_DISPATCH)
7474 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7475 else if (curproxy->options & PR_O_HTTP_PROXY)
7476 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7477 else if (curproxy->options & PR_O_TRANSP)
7478 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007479
Willy Tarreau1620ec32011-08-06 17:05:02 +02007480 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7481 if (curproxy->options & PR_O_DISABLE404) {
7482 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7483 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7484 err_code |= ERR_WARN;
7485 curproxy->options &= ~PR_O_DISABLE404;
7486 }
7487 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7488 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7489 "send-state", proxy_type_str(curproxy), curproxy->id);
7490 err_code |= ERR_WARN;
7491 curproxy->options &= ~PR_O2_CHK_SNDST;
7492 }
Willy Tarreauef781042010-01-27 11:53:01 +01007493 }
7494
Simon Horman98637e52014-06-20 12:30:16 +09007495 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7496 if (!global.external_check) {
7497 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7498 curproxy->id, "option external-check");
7499 cfgerr++;
7500 }
7501 if (!curproxy->check_command) {
7502 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7503 curproxy->id, "option external-check");
7504 cfgerr++;
7505 }
7506 }
7507
Simon Horman64e34162015-02-06 11:11:57 +09007508 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007509 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7510 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007511 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7512 "'email-alert myhostname', or 'email-alert to' "
7513 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007514 "to be present).\n",
7515 proxy_type_str(curproxy), curproxy->id);
7516 err_code |= ERR_WARN;
7517 free_email_alert(curproxy);
7518 }
7519 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007520 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007521 }
7522
Simon Horman98637e52014-06-20 12:30:16 +09007523 if (curproxy->check_command) {
7524 int clear = 0;
7525 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7526 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7527 "external-check command", proxy_type_str(curproxy), curproxy->id);
7528 err_code |= ERR_WARN;
7529 clear = 1;
7530 }
7531 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007532 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007533 curproxy->id, "external-check command");
7534 cfgerr++;
7535 }
7536 if (clear) {
7537 free(curproxy->check_command);
7538 curproxy->check_command = NULL;
7539 }
7540 }
7541
7542 if (curproxy->check_path) {
7543 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7544 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7545 "external-check path", proxy_type_str(curproxy), curproxy->id);
7546 err_code |= ERR_WARN;
7547 free(curproxy->check_path);
7548 curproxy->check_path = NULL;
7549 }
7550 }
7551
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007552 /* if a default backend was specified, let's find it */
7553 if (curproxy->defbe.name) {
7554 struct proxy *target;
7555
Willy Tarreauafb39922015-05-26 12:04:09 +02007556 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007557 if (!target) {
7558 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7559 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007560 cfgerr++;
7561 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007562 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7563 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007564 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007565 } else if (target->mode != curproxy->mode &&
7566 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7567
7568 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7569 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7570 curproxy->conf.file, curproxy->conf.line,
7571 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7572 target->conf.file, target->conf.line);
7573 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007574 } else {
7575 free(curproxy->defbe.name);
7576 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007577
7578 /* Emit a warning if this proxy also has some servers */
7579 if (curproxy->srv) {
7580 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7581 curproxy->id);
7582 err_code |= ERR_WARN;
7583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007584 }
7585 }
7586
Willy Tarreau55ea7572007-06-17 19:56:27 +02007587 /* find the target proxy for 'use_backend' rules */
7588 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007589 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007590 struct logformat_node *node;
7591 char *pxname;
7592
7593 /* Try to parse the string as a log format expression. If the result
7594 * of the parsing is only one entry containing a simple string, then
7595 * it's a standard string corresponding to a static rule, thus the
7596 * parsing is cancelled and be.name is restored to be resolved.
7597 */
7598 pxname = rule->be.name;
7599 LIST_INIT(&rule->be.expr);
7600 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7601 curproxy->conf.args.file, curproxy->conf.args.line);
7602 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7603
7604 if (!LIST_ISEMPTY(&rule->be.expr)) {
7605 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7606 rule->dynamic = 1;
7607 free(pxname);
7608 continue;
7609 }
7610 /* simple string: free the expression and fall back to static rule */
7611 free(node->arg);
7612 free(node);
7613 }
7614
7615 rule->dynamic = 0;
7616 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007617
Willy Tarreauafb39922015-05-26 12:04:09 +02007618 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007619 if (!target) {
7620 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7621 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007622 cfgerr++;
7623 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007624 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7625 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007626 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007627 } else if (target->mode != curproxy->mode &&
7628 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7629
7630 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7631 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7632 curproxy->conf.file, curproxy->conf.line,
7633 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7634 target->conf.file, target->conf.line);
7635 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007636 } else {
7637 free((void *)rule->be.name);
7638 rule->be.backend = target;
7639 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007640 }
7641
Willy Tarreau64ab6072014-09-16 12:17:36 +02007642 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007643 list_for_each_entry(srule, &curproxy->server_rules, list) {
7644 struct server *target = findserver(curproxy, srule->srv.name);
7645
7646 if (!target) {
7647 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7648 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7649 cfgerr++;
7650 continue;
7651 }
7652 free((void *)srule->srv.name);
7653 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007654 }
7655
Emeric Brunb982a3d2010-01-04 15:45:53 +01007656 /* find the target table for 'stick' rules */
7657 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7658 struct proxy *target;
7659
Emeric Brun1d33b292010-01-04 15:47:17 +01007660 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7661 if (mrule->flags & STK_IS_STORE)
7662 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7663
Emeric Brunb982a3d2010-01-04 15:45:53 +01007664 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007665 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007666 else
7667 target = curproxy;
7668
7669 if (!target) {
7670 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7671 curproxy->id, mrule->table.name);
7672 cfgerr++;
7673 }
7674 else if (target->table.size == 0) {
7675 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7676 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7677 cfgerr++;
7678 }
Willy Tarreau12785782012-04-27 21:37:17 +02007679 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7680 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007681 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7682 cfgerr++;
7683 }
7684 else {
7685 free((void *)mrule->table.name);
7686 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007687 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007688 }
7689 }
7690
7691 /* find the target table for 'store response' rules */
7692 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7693 struct proxy *target;
7694
Emeric Brun1d33b292010-01-04 15:47:17 +01007695 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7696
Emeric Brunb982a3d2010-01-04 15:45:53 +01007697 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007698 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007699 else
7700 target = curproxy;
7701
7702 if (!target) {
7703 Alert("Proxy '%s': unable to find store table '%s'.\n",
7704 curproxy->id, mrule->table.name);
7705 cfgerr++;
7706 }
7707 else if (target->table.size == 0) {
7708 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7709 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7710 cfgerr++;
7711 }
Willy Tarreau12785782012-04-27 21:37:17 +02007712 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7713 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007714 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7715 cfgerr++;
7716 }
7717 else {
7718 free((void *)mrule->table.name);
7719 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007720 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007721 }
7722 }
7723
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007724 /* find the target table for 'tcp-request' layer 4 rules */
7725 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7726 struct proxy *target;
7727
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007728 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007729 continue;
7730
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007731 if (trule->arg.trk_ctr.table.n)
7732 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007733 else
7734 target = curproxy;
7735
7736 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007737 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007738 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007739 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007740 cfgerr++;
7741 }
7742 else if (target->table.size == 0) {
7743 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007744 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007745 cfgerr++;
7746 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007747 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007748 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007749 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007750 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007751 cfgerr++;
7752 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007753 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007754 free(trule->arg.trk_ctr.table.n);
7755 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007756 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007757 * to pass a list of counters to track and allocate them right here using
7758 * stktable_alloc_data_type().
7759 */
7760 }
7761 }
7762
Willy Tarreaud1f96522010-08-03 19:34:32 +02007763 /* find the target table for 'tcp-request' layer 6 rules */
7764 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7765 struct proxy *target;
7766
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007767 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007768 continue;
7769
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007770 if (trule->arg.trk_ctr.table.n)
7771 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007772 else
7773 target = curproxy;
7774
7775 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007776 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007777 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007778 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007779 cfgerr++;
7780 }
7781 else if (target->table.size == 0) {
7782 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007783 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007784 cfgerr++;
7785 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007786 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007787 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007788 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007789 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007790 cfgerr++;
7791 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007792 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007793 free(trule->arg.trk_ctr.table.n);
7794 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007795 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007796 * to pass a list of counters to track and allocate them right here using
7797 * stktable_alloc_data_type().
7798 */
7799 }
7800 }
7801
Baptiste Assmanne9544932015-11-03 23:31:35 +01007802 /* parse http-request capture rules to ensure id really exists */
7803 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7804 if (hrqrule->action != ACT_CUSTOM ||
7805 hrqrule->action_ptr != http_action_req_capture_by_id)
7806 continue;
7807
7808 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7809 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7810 curproxy->id, hrqrule->arg.capid.idx);
7811 cfgerr++;
7812 }
7813 }
7814
7815 /* parse http-response capture rules to ensure id really exists */
7816 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7817 if (hrqrule->action != ACT_CUSTOM ||
7818 hrqrule->action_ptr != http_action_res_capture_by_id)
7819 continue;
7820
7821 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7822 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7823 curproxy->id, hrqrule->arg.capid.idx);
7824 cfgerr++;
7825 }
7826 }
7827
Willy Tarreau09448f72014-06-25 18:12:15 +02007828 /* find the target table for 'http-request' layer 7 rules */
7829 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7830 struct proxy *target;
7831
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007832 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007833 continue;
7834
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007835 if (hrqrule->arg.trk_ctr.table.n)
7836 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007837 else
7838 target = curproxy;
7839
7840 if (!target) {
7841 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007842 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007843 http_req_trk_idx(hrqrule->action));
7844 cfgerr++;
7845 }
7846 else if (target->table.size == 0) {
7847 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007848 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007849 cfgerr++;
7850 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007851 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007852 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007853 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007854 http_req_trk_idx(hrqrule->action));
7855 cfgerr++;
7856 }
7857 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007858 free(hrqrule->arg.trk_ctr.table.n);
7859 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007860 /* Note: if we decide to enhance the track-sc syntax, we may be able
7861 * to pass a list of counters to track and allocate them right here using
7862 * stktable_alloc_data_type().
7863 */
7864 }
7865 }
7866
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007867 /* move any "block" rules at the beginning of the http-request rules */
7868 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7869 /* insert block_rules into http_req_rules at the beginning */
7870 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7871 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7872 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7873 curproxy->http_req_rules.n = curproxy->block_rules.n;
7874 LIST_INIT(&curproxy->block_rules);
7875 }
7876
Emeric Brun32da3c42010-09-23 18:39:19 +02007877 if (curproxy->table.peers.name) {
7878 struct peers *curpeers = peers;
7879
7880 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7881 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7882 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007883 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007884 break;
7885 }
7886 }
7887
7888 if (!curpeers) {
7889 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7890 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007891 free((void *)curproxy->table.peers.name);
7892 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007893 cfgerr++;
7894 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007895 else if (curpeers->state == PR_STSTOPPED) {
7896 /* silently disable this peers section */
7897 curproxy->table.peers.p = NULL;
7898 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007899 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007900 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7901 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007902 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007903 cfgerr++;
7904 }
7905 }
7906
Simon Horman9dc49962015-01-30 11:22:59 +09007907
7908 if (curproxy->email_alert.mailers.name) {
7909 struct mailers *curmailers = mailers;
7910
7911 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7912 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7913 free(curproxy->email_alert.mailers.name);
7914 curproxy->email_alert.mailers.m = curmailers;
7915 curmailers->users++;
7916 break;
7917 }
7918 }
7919
7920 if (!curmailers) {
7921 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7922 curproxy->id, curproxy->email_alert.mailers.name);
7923 free_email_alert(curproxy);
7924 cfgerr++;
7925 }
7926 }
7927
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007928 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007929 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007930 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7931 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7932 "proxy", curproxy->id);
7933 cfgerr++;
7934 goto out_uri_auth_compat;
7935 }
7936
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007937 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007938 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007939 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007940 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007941
Willy Tarreau95fa4692010-02-01 13:05:50 +01007942 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7943 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007944
7945 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007946 uri_auth_compat_req[i++] = "realm";
7947 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7948 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007949
Willy Tarreau95fa4692010-02-01 13:05:50 +01007950 uri_auth_compat_req[i++] = "unless";
7951 uri_auth_compat_req[i++] = "{";
7952 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7953 uri_auth_compat_req[i++] = "}";
7954 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007955
Willy Tarreauff011f22011-01-06 17:51:27 +01007956 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7957 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007958 cfgerr++;
7959 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007960 }
7961
Willy Tarreauff011f22011-01-06 17:51:27 +01007962 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007963
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007964 if (curproxy->uri_auth->auth_realm) {
7965 free(curproxy->uri_auth->auth_realm);
7966 curproxy->uri_auth->auth_realm = NULL;
7967 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007968
7969 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007970 }
7971out_uri_auth_compat:
7972
Dragan Dosen43885c72015-10-01 13:18:13 +02007973 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02007974 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02007975 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
7976 if (!curproxy->conf.logformat_sd_string) {
7977 /* set the default logformat_sd_string */
7978 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
7979 }
Dragan Dosen1322d092015-09-22 16:05:32 +02007980 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02007981 }
Dragan Dosen1322d092015-09-22 16:05:32 +02007982 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02007983
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007984 /* compile the log format */
7985 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007986 if (curproxy->conf.logformat_string != default_http_log_format &&
7987 curproxy->conf.logformat_string != default_tcp_log_format &&
7988 curproxy->conf.logformat_string != clf_http_log_format)
7989 free(curproxy->conf.logformat_string);
7990 curproxy->conf.logformat_string = NULL;
7991 free(curproxy->conf.lfs_file);
7992 curproxy->conf.lfs_file = NULL;
7993 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007994
7995 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
7996 free(curproxy->conf.logformat_sd_string);
7997 curproxy->conf.logformat_sd_string = NULL;
7998 free(curproxy->conf.lfsd_file);
7999 curproxy->conf.lfsd_file = NULL;
8000 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008001 }
8002
Willy Tarreau62a61232013-04-12 18:13:46 +02008003 if (curproxy->conf.logformat_string) {
8004 curproxy->conf.args.ctx = ARGC_LOG;
8005 curproxy->conf.args.file = curproxy->conf.lfs_file;
8006 curproxy->conf.args.line = curproxy->conf.lfs_line;
8007 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008008 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008009 curproxy->conf.args.file = NULL;
8010 curproxy->conf.args.line = 0;
8011 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008012
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008013 if (curproxy->conf.logformat_sd_string) {
8014 curproxy->conf.args.ctx = ARGC_LOGSD;
8015 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8016 curproxy->conf.args.line = curproxy->conf.lfsd_line;
8017 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
8018 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
8019 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
8020 curproxy->conf.args.file = NULL;
8021 curproxy->conf.args.line = 0;
8022 }
8023
Willy Tarreau62a61232013-04-12 18:13:46 +02008024 if (curproxy->conf.uniqueid_format_string) {
8025 curproxy->conf.args.ctx = ARGC_UIF;
8026 curproxy->conf.args.file = curproxy->conf.uif_file;
8027 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01008028 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08008029 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008030 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008031 curproxy->conf.args.file = NULL;
8032 curproxy->conf.args.line = 0;
8033 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008034
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008035 /* only now we can check if some args remain unresolved.
8036 * This must be done after the users and groups resolution.
8037 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008038 cfgerr += smp_resolve_args(curproxy);
8039 if (!cfgerr)
8040 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008041
Willy Tarreau2738a142006-07-08 17:28:09 +02008042 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008043 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008044 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008045 (!curproxy->timeout.connect ||
8046 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008047 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008048 " | While not properly invalid, you will certainly encounter various problems\n"
8049 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008050 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008051 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008052 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008053 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008054
Willy Tarreau1fa31262007-12-03 00:36:16 +01008055 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8056 * We must still support older configurations, so let's find out whether those
8057 * parameters have been set or must be copied from contimeouts.
8058 */
8059 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008060 if (!curproxy->timeout.tarpit ||
8061 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008062 /* tarpit timeout not set. We search in the following order:
8063 * default.tarpit, curr.connect, default.connect.
8064 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008065 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008066 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008067 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008068 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008069 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008070 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008071 }
8072 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008073 (!curproxy->timeout.queue ||
8074 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008075 /* queue timeout not set. We search in the following order:
8076 * default.queue, curr.connect, default.connect.
8077 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008078 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008079 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008080 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008081 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008082 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008083 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008084 }
8085 }
8086
Willy Tarreau1620ec32011-08-06 17:05:02 +02008087 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008088 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
8089 curproxy->check_req = (char *)malloc(curproxy->check_len);
8090 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008091 }
8092
Willy Tarreau215663d2014-06-13 18:30:23 +02008093 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8094 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8095 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8096 proxy_type_str(curproxy), curproxy->id);
8097 err_code |= ERR_WARN;
8098 }
8099
Willy Tarreau193b8c62012-11-22 00:17:38 +01008100 /* ensure that cookie capture length is not too large */
8101 if (curproxy->capture_len >= global.tune.cookie_len) {
8102 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8103 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8104 err_code |= ERR_WARN;
8105 curproxy->capture_len = global.tune.cookie_len - 1;
8106 }
8107
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008108 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008109 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008110 curproxy->req_cap_pool = create_pool("ptrcap",
8111 curproxy->nb_req_cap * sizeof(char *),
8112 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008113 }
8114
8115 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008116 curproxy->rsp_cap_pool = create_pool("ptrcap",
8117 curproxy->nb_rsp_cap * sizeof(char *),
8118 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008119 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008120
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008121 switch (curproxy->load_server_state_from_file) {
8122 case PR_SRV_STATE_FILE_UNSPEC:
8123 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8124 break;
8125 case PR_SRV_STATE_FILE_GLOBAL:
8126 if (!global.server_state_file) {
8127 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",
8128 curproxy->id);
8129 err_code |= ERR_WARN;
8130 }
8131 break;
8132 }
8133
Willy Tarreaubaaee002006-06-26 02:48:02 +02008134 /* first, we will invert the servers list order */
8135 newsrv = NULL;
8136 while (curproxy->srv) {
8137 struct server *next;
8138
8139 next = curproxy->srv->next;
8140 curproxy->srv->next = newsrv;
8141 newsrv = curproxy->srv;
8142 if (!next)
8143 break;
8144 curproxy->srv = next;
8145 }
8146
Willy Tarreau17edc812014-01-03 12:14:34 +01008147 /* Check that no server name conflicts. This causes trouble in the stats.
8148 * We only emit a warning for the first conflict affecting each server,
8149 * in order to avoid combinatory explosion if all servers have the same
8150 * name. We do that only for servers which do not have an explicit ID,
8151 * because these IDs were made also for distinguishing them and we don't
8152 * want to annoy people who correctly manage them.
8153 */
8154 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8155 struct server *other_srv;
8156
8157 if (newsrv->puid)
8158 continue;
8159
8160 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8161 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8162 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8163 newsrv->conf.file, newsrv->conf.line,
8164 proxy_type_str(curproxy), curproxy->id,
8165 newsrv->id, other_srv->conf.line);
8166 break;
8167 }
8168 }
8169 }
8170
Willy Tarreaudd701652010-05-25 23:03:02 +02008171 /* assign automatic UIDs to servers which don't have one yet */
8172 next_id = 1;
8173 newsrv = curproxy->srv;
8174 while (newsrv != NULL) {
8175 if (!newsrv->puid) {
8176 /* server ID not set, use automatic numbering with first
8177 * spare entry starting with next_svid.
8178 */
8179 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8180 newsrv->conf.id.key = newsrv->puid = next_id;
8181 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8182 }
8183 next_id++;
8184 newsrv = newsrv->next;
8185 }
8186
Willy Tarreau20697042007-11-15 23:26:18 +01008187 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008188 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008189
Willy Tarreau62c3be22012-01-20 13:12:32 +01008190 /*
8191 * If this server supports a maxconn parameter, it needs a dedicated
8192 * tasks to fill the emptied slots when a connection leaves.
8193 * Also, resolve deferred tracking dependency if needed.
8194 */
8195 newsrv = curproxy->srv;
8196 while (newsrv != NULL) {
8197 if (newsrv->minconn > newsrv->maxconn) {
8198 /* Only 'minconn' was specified, or it was higher than or equal
8199 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8200 * this will avoid further useless expensive computations.
8201 */
8202 newsrv->maxconn = newsrv->minconn;
8203 } else if (newsrv->maxconn && !newsrv->minconn) {
8204 /* minconn was not specified, so we set it to maxconn */
8205 newsrv->minconn = newsrv->maxconn;
8206 }
8207
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008208#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008209 if (newsrv->use_ssl || newsrv->check.use_ssl)
8210 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008211#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008212
Willy Tarreau2f075e92013-12-03 11:11:34 +01008213 /* set the check type on the server */
8214 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8215
Willy Tarreau62c3be22012-01-20 13:12:32 +01008216 if (newsrv->trackit) {
8217 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008218 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008219 char *pname, *sname;
8220
8221 pname = newsrv->trackit;
8222 sname = strrchr(pname, '/');
8223
8224 if (sname)
8225 *sname++ = '\0';
8226 else {
8227 sname = pname;
8228 pname = NULL;
8229 }
8230
8231 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008232 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008233 if (!px) {
8234 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8235 proxy_type_str(curproxy), curproxy->id,
8236 newsrv->id, pname);
8237 cfgerr++;
8238 goto next_srv;
8239 }
8240 } else
8241 px = curproxy;
8242
8243 srv = findserver(px, sname);
8244 if (!srv) {
8245 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8246 proxy_type_str(curproxy), curproxy->id,
8247 newsrv->id, sname);
8248 cfgerr++;
8249 goto next_srv;
8250 }
8251
Willy Tarreau32091232014-05-16 13:52:00 +02008252 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8253 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8254 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008255 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008256 "tracking as it does not have any check nor agent enabled.\n",
8257 proxy_type_str(curproxy), curproxy->id,
8258 newsrv->id, px->id, srv->id);
8259 cfgerr++;
8260 goto next_srv;
8261 }
8262
8263 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8264
8265 if (loop) {
8266 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8267 "belongs to a tracking chain looping back to %s/%s.\n",
8268 proxy_type_str(curproxy), curproxy->id,
8269 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008270 cfgerr++;
8271 goto next_srv;
8272 }
8273
8274 if (curproxy != px &&
8275 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8276 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8277 "tracking: disable-on-404 option inconsistency.\n",
8278 proxy_type_str(curproxy), curproxy->id,
8279 newsrv->id, px->id, srv->id);
8280 cfgerr++;
8281 goto next_srv;
8282 }
8283
8284 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008285 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008286 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008287 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008288 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008289 }
8290
8291 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008292 newsrv->tracknext = srv->trackers;
8293 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008294
8295 free(newsrv->trackit);
8296 newsrv->trackit = NULL;
8297 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008298
8299 /*
8300 * resolve server's resolvers name and update the resolvers pointer
8301 * accordingly
8302 */
8303 if (newsrv->resolvers_id) {
8304 struct dns_resolvers *curr_resolvers;
8305 int found;
8306
8307 found = 0;
8308 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8309 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8310 found = 1;
8311 break;
8312 }
8313 }
8314
8315 if (!found) {
8316 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8317 proxy_type_str(curproxy), curproxy->id,
8318 newsrv->id, newsrv->resolvers_id);
8319 cfgerr++;
8320 } else {
8321 free(newsrv->resolvers_id);
8322 newsrv->resolvers_id = NULL;
8323 if (newsrv->resolution)
8324 newsrv->resolution->resolvers = curr_resolvers;
8325 }
8326 }
8327 else {
8328 /* if no resolvers section associated to this server
8329 * we can clean up the associated resolution structure
8330 */
8331 if (newsrv->resolution) {
8332 free(newsrv->resolution->hostname_dn);
8333 newsrv->resolution->hostname_dn = NULL;
8334 free(newsrv->resolution);
8335 newsrv->resolution = NULL;
8336 }
8337 }
8338
Willy Tarreau62c3be22012-01-20 13:12:32 +01008339 next_srv:
8340 newsrv = newsrv->next;
8341 }
8342
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008343 /* We have to initialize the server lookup mechanism depending
8344 * on what LB algorithm was choosen.
8345 */
8346
8347 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8348 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8349 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008350 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8351 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8352 init_server_map(curproxy);
8353 } else {
8354 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8355 fwrr_init_server_groups(curproxy);
8356 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008357 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008358
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008359 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008360 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8361 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8362 fwlc_init_server_tree(curproxy);
8363 } else {
8364 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8365 fas_init_server_tree(curproxy);
8366 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008367 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008368
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008369 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008370 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8371 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8372 chash_init_server_tree(curproxy);
8373 } else {
8374 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8375 init_server_map(curproxy);
8376 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008377 break;
8378 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008379
8380 if (curproxy->options & PR_O_LOGASAP)
8381 curproxy->to_log &= ~LW_BYTES;
8382
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008383 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008384 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8385 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008386 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8387 proxy_type_str(curproxy), curproxy->id);
8388 err_code |= ERR_WARN;
8389 }
8390
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008391 if (curproxy->mode != PR_MODE_HTTP) {
8392 int optnum;
8393
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008394 if (curproxy->uri_auth) {
8395 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8396 proxy_type_str(curproxy), curproxy->id);
8397 err_code |= ERR_WARN;
8398 curproxy->uri_auth = NULL;
8399 }
8400
Willy Tarreau87cf5142011-08-19 22:57:24 +02008401 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008402 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8403 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8404 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008405 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008406 }
8407
8408 if (curproxy->options & PR_O_ORGTO) {
8409 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8410 "originalto", proxy_type_str(curproxy), curproxy->id);
8411 err_code |= ERR_WARN;
8412 curproxy->options &= ~PR_O_ORGTO;
8413 }
8414
8415 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8416 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8417 (curproxy->cap & cfg_opts[optnum].cap) &&
8418 (curproxy->options & cfg_opts[optnum].val)) {
8419 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8420 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8421 err_code |= ERR_WARN;
8422 curproxy->options &= ~cfg_opts[optnum].val;
8423 }
8424 }
8425
8426 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8427 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8428 (curproxy->cap & cfg_opts2[optnum].cap) &&
8429 (curproxy->options2 & cfg_opts2[optnum].val)) {
8430 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8431 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8432 err_code |= ERR_WARN;
8433 curproxy->options2 &= ~cfg_opts2[optnum].val;
8434 }
8435 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008436
Willy Tarreau29fbe512015-08-20 19:35:14 +02008437#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008438 if (curproxy->conn_src.bind_hdr_occ) {
8439 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008440 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008441 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008442 err_code |= ERR_WARN;
8443 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008444#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008445 }
8446
Willy Tarreaubaaee002006-06-26 02:48:02 +02008447 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008448 * ensure that we're not cross-dressing a TCP server into HTTP.
8449 */
8450 newsrv = curproxy->srv;
8451 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008452 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008453 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8454 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008455 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008456 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008457
Willy Tarreau0cec3312011-10-31 13:49:26 +01008458 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8459 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8460 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8461 err_code |= ERR_WARN;
8462 }
8463
Willy Tarreauc93cd162014-05-13 15:54:22 +02008464 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008465 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8466 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8467 err_code |= ERR_WARN;
8468 }
8469
Willy Tarreau29fbe512015-08-20 19:35:14 +02008470#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008471 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8472 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008473 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 +01008474 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008475 err_code |= ERR_WARN;
8476 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008477#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008478 newsrv = newsrv->next;
8479 }
8480
Willy Tarreaue42bd962014-09-16 16:21:19 +02008481 /* check if we have a frontend with "tcp-request content" looking at L7
8482 * with no inspect-delay
8483 */
8484 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8485 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008486 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008487 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008488 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008489 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008490 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008491 break;
8492 }
8493
8494 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8495 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8496 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8497 " This means that these rules will randomly find their contents. This can be fixed by"
8498 " setting the tcp-request inspect-delay.\n",
8499 proxy_type_str(curproxy), curproxy->id);
8500 err_code |= ERR_WARN;
8501 }
8502 }
8503
Christopher Fauletd7c91962015-04-30 11:48:27 +02008504 /* Check filter configuration, if any */
8505 cfgerr += flt_check(curproxy);
8506
Willy Tarreauc1a21672009-08-16 22:37:44 +02008507 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008508 if (!curproxy->accept)
8509 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008510
Willy Tarreauc1a21672009-08-16 22:37:44 +02008511 if (curproxy->tcp_req.inspect_delay ||
8512 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008513 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008514
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008515 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008516 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008517 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008518 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008519
8520 /* both TCP and HTTP must check switching rules */
8521 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008522
8523 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008524 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008525 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8526 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008527 if (curproxy->mode == PR_MODE_HTTP) {
8528 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8529 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8530 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008531 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008532 }
8533
8534 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008535 if (curproxy->tcp_req.inspect_delay ||
8536 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8537 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8538
Emeric Brun97679e72010-09-23 17:56:44 +02008539 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8540 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8541
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008542 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008543 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008544 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008545 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008546
8547 /* If the backend does requires RDP cookie persistence, we have to
8548 * enable the corresponding analyser.
8549 */
8550 if (curproxy->options2 & PR_O2_RDPC_PRST)
8551 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008552
8553 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008554 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008555 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8556 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008557 if (curproxy->mode == PR_MODE_HTTP) {
8558 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8559 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8560 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008561 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008562 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008563 }
8564
8565 /***********************************************************/
8566 /* At this point, target names have already been resolved. */
8567 /***********************************************************/
8568
8569 /* Check multi-process mode compatibility */
8570
8571 if (global.nbproc > 1 && global.stats_fe) {
8572 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8573 unsigned long mask;
8574
8575 mask = nbits(global.nbproc);
8576 if (global.stats_fe->bind_proc)
8577 mask &= global.stats_fe->bind_proc;
8578
8579 if (bind_conf->bind_proc)
8580 mask &= bind_conf->bind_proc;
8581
8582 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008583 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008584 break;
8585 }
8586 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8587 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");
8588 }
8589 }
8590
8591 /* Make each frontend inherit bind-process from its listeners when not specified. */
8592 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8593 if (curproxy->bind_proc)
8594 continue;
8595
8596 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8597 unsigned long mask;
8598
Willy Tarreaue428b082015-05-04 21:57:58 +02008599 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008600 curproxy->bind_proc |= mask;
8601 }
8602
8603 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008604 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008605 }
8606
8607 if (global.stats_fe) {
8608 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8609 unsigned long mask;
8610
Willy Tarreaue428b082015-05-04 21:57:58 +02008611 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008612 global.stats_fe->bind_proc |= mask;
8613 }
8614 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008615 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008616 }
8617
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008618 /* propagate bindings from frontends to backends. Don't do it if there
8619 * are any fatal errors as we must not call it with unresolved proxies.
8620 */
8621 if (!cfgerr) {
8622 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8623 if (curproxy->cap & PR_CAP_FE)
8624 propagate_processes(curproxy, NULL);
8625 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008626 }
8627
8628 /* Bind each unbound backend to all processes when not specified. */
8629 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8630 if (curproxy->bind_proc)
8631 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008632 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008633 }
8634
8635 /*******************************************************/
8636 /* At this step, all proxies have a non-null bind_proc */
8637 /*******************************************************/
8638
8639 /* perform the final checks before creating tasks */
8640
8641 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8642 struct listener *listener;
8643 unsigned int next_id;
8644 int nbproc;
8645
David Carliere6c39412015-07-02 07:00:17 +00008646 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008647
Emeric Brunc52962f2012-11-15 18:28:02 +01008648#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008649 /* Configure SSL for each bind line.
8650 * Note: if configuration fails at some point, the ->ctx member
8651 * remains NULL so that listeners can later detach.
8652 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008653 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008654 int alloc_ctx;
8655
Emeric Brunc52962f2012-11-15 18:28:02 +01008656 if (!bind_conf->is_ssl) {
8657 if (bind_conf->default_ctx) {
8658 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8659 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8660 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008661 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008662 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008663 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008664 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008665 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008666 cfgerr++;
8667 continue;
8668 }
8669
Emeric Brun8dc60392014-05-09 13:52:00 +02008670 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008671 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008672 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8673 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");
8674 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008675 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008676 cfgerr++;
8677 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008678 }
8679
Emeric Brunfc0421f2012-09-07 17:30:07 +02008680 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008681 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008682
8683 /* initialize CA variables if the certificates generation is enabled */
8684 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008685 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008686#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008687
Willy Tarreaue6b98942007-10-29 01:09:36 +01008688 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008689 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008690 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008691 if (!listener->luid) {
8692 /* listener ID not set, use automatic numbering with first
8693 * spare entry starting with next_luid.
8694 */
8695 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8696 listener->conf.id.key = listener->luid = next_id;
8697 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008698 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008699 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008700
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008701 /* enable separate counters */
8702 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8703 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008704 if (!listener->name)
8705 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008706 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008707
Willy Tarreaue6b98942007-10-29 01:09:36 +01008708 if (curproxy->options & PR_O_TCP_NOLING)
8709 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008710 if (!listener->maxconn)
8711 listener->maxconn = curproxy->maxconn;
8712 if (!listener->backlog)
8713 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008714 if (!listener->maxaccept)
8715 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8716
8717 /* we want to have an optimal behaviour on single process mode to
8718 * maximize the work at once, but in multi-process we want to keep
8719 * some fairness between processes, so we target half of the max
8720 * number of events to be balanced over all the processes the proxy
8721 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8722 * used to disable the limit.
8723 */
8724 if (listener->maxaccept > 0) {
8725 if (nbproc > 1)
8726 listener->maxaccept = (listener->maxaccept + 1) / 2;
8727 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8728 }
8729
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008730 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008731 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008732 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008733 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008734
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008735 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8736 listener->options |= LI_O_TCP_RULES;
8737
Willy Tarreaude3041d2010-05-31 10:56:17 +02008738 if (curproxy->mon_mask.s_addr)
8739 listener->options |= LI_O_CHK_MONNET;
8740
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008741 /* smart accept mode is automatic in HTTP mode */
8742 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008743 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008744 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8745 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008746 }
8747
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008748 /* Release unused SSL configs */
8749 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8750 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008751 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008752#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008753 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008754 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008755 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008756 free(bind_conf->ca_sign_file);
8757 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008758 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008759 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008760 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008761 if(bind_conf->keys_ref) {
8762 free(bind_conf->keys_ref->filename);
8763 free(bind_conf->keys_ref->tlskeys);
8764 free(bind_conf->keys_ref);
8765 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008766#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008767 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008768
Willy Tarreau102df612014-05-07 23:56:38 +02008769 if (nbproc > 1) {
8770 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008771 int count, maxproc = 0;
8772
8773 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008774 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008775 if (count > maxproc)
8776 maxproc = count;
8777 }
8778 /* backends have 0, frontends have 1 or more */
8779 if (maxproc != 1)
8780 Warning("Proxy '%s': in multi-process mode, stats will be"
8781 " limited to process assigned to the current request.\n",
8782 curproxy->id);
8783
Willy Tarreau102df612014-05-07 23:56:38 +02008784 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8785 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8786 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008787 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008788 }
Willy Tarreau102df612014-05-07 23:56:38 +02008789 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8790 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8791 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008792 }
8793 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008794
8795 /* create the task associated with the proxy */
8796 curproxy->task = task_new();
8797 if (curproxy->task) {
8798 curproxy->task->context = curproxy;
8799 curproxy->task->process = manage_proxy;
8800 /* no need to queue, it will be done automatically if some
8801 * listener gets limited.
8802 */
8803 curproxy->task->expire = TICK_ETERNITY;
8804 } else {
8805 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8806 curproxy->id);
8807 cfgerr++;
8808 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008809 }
8810
Willy Tarreaufbb78422011-06-05 15:38:35 +02008811 /* automatically compute fullconn if not set. We must not do it in the
8812 * loop above because cross-references are not yet fully resolved.
8813 */
8814 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8815 /* If <fullconn> is not set, let's set it to 10% of the sum of
8816 * the possible incoming frontend's maxconns.
8817 */
8818 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8819 struct proxy *fe;
8820 int total = 0;
8821
8822 /* sum up the number of maxconns of frontends which
8823 * reference this backend at least once or which are
8824 * the same one ('listen').
8825 */
8826 for (fe = proxy; fe; fe = fe->next) {
8827 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008828 int found = 0;
8829
8830 if (!(fe->cap & PR_CAP_FE))
8831 continue;
8832
8833 if (fe == curproxy) /* we're on a "listen" instance */
8834 found = 1;
8835
8836 if (fe->defbe.be == curproxy) /* "default_backend" */
8837 found = 1;
8838
8839 /* check if a "use_backend" rule matches */
8840 if (!found) {
8841 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008842 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008843 found = 1;
8844 break;
8845 }
8846 }
8847 }
8848
Willy Tarreaufbb78422011-06-05 15:38:35 +02008849 /* now we've checked all possible ways to reference a backend
8850 * from a frontend.
8851 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008852 if (!found)
8853 continue;
8854 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008855 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008856 /* we have the sum of the maxconns in <total>. We only
8857 * keep 10% of that sum to set the default fullconn, with
8858 * a hard minimum of 1 (to avoid a divide by zero).
8859 */
8860 curproxy->fullconn = (total + 9) / 10;
8861 if (!curproxy->fullconn)
8862 curproxy->fullconn = 1;
8863 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008864 }
8865
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008866 /*
8867 * Recount currently required checks.
8868 */
8869
8870 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8871 int optnum;
8872
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008873 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8874 if (curproxy->options & cfg_opts[optnum].val)
8875 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008876
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008877 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8878 if (curproxy->options2 & cfg_opts2[optnum].val)
8879 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008880 }
8881
Willy Tarreau0fca4832015-05-01 19:12:05 +02008882 /* compute the required process bindings for the peers */
8883 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8884 if (curproxy->table.peers.p)
8885 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8886
Willy Tarreau122541c2011-09-07 21:24:49 +02008887 if (peers) {
8888 struct peers *curpeers = peers, **last;
8889 struct peer *p, *pb;
8890
Willy Tarreau1e273012015-05-01 19:15:17 +02008891 /* Remove all peers sections which don't have a valid listener,
8892 * which are not used by any table, or which are bound to more
8893 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008894 */
8895 last = &peers;
8896 while (*last) {
8897 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008898
8899 if (curpeers->state == PR_STSTOPPED) {
8900 /* the "disabled" keyword was present */
8901 if (curpeers->peers_fe)
8902 stop_proxy(curpeers->peers_fe);
8903 curpeers->peers_fe = NULL;
8904 }
8905 else if (!curpeers->peers_fe) {
8906 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8907 curpeers->id, localpeer);
8908 }
David Carliere6c39412015-07-02 07:00:17 +00008909 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008910 /* either it's totally stopped or too much used */
8911 if (curpeers->peers_fe->bind_proc) {
8912 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008913 "running in different processes (%d different ones). "
8914 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008915 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008916 cfgerr++;
8917 }
8918 stop_proxy(curpeers->peers_fe);
8919 curpeers->peers_fe = NULL;
8920 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008921 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008922 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008923 last = &curpeers->next;
8924 continue;
8925 }
8926
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008927 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008928 p = curpeers->remote;
8929 while (p) {
8930 pb = p->next;
8931 free(p->id);
8932 free(p);
8933 p = pb;
8934 }
8935
8936 /* Destroy and unlink this curpeers section.
8937 * Note: curpeers is backed up into *last.
8938 */
8939 free(curpeers->id);
8940 curpeers = curpeers->next;
8941 free(*last);
8942 *last = curpeers;
8943 }
8944 }
8945
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008946 /* initialize stick-tables on backend capable proxies. This must not
8947 * be done earlier because the data size may be discovered while parsing
8948 * other proxies.
8949 */
8950 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8951 if (curproxy->state == PR_STSTOPPED)
8952 continue;
8953
8954 if (!stktable_init(&curproxy->table)) {
8955 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8956 cfgerr++;
8957 }
8958 }
8959
Simon Horman0d16a402015-01-30 11:22:58 +09008960 if (mailers) {
8961 struct mailers *curmailers = mailers, **last;
8962 struct mailer *m, *mb;
8963
8964 /* Remove all mailers sections which don't have a valid listener.
8965 * This can happen when a mailers section is never referenced.
8966 */
8967 last = &mailers;
8968 while (*last) {
8969 curmailers = *last;
8970 if (curmailers->users) {
8971 last = &curmailers->next;
8972 continue;
8973 }
8974
8975 Warning("Removing incomplete section 'mailers %s'.\n",
8976 curmailers->id);
8977
8978 m = curmailers->mailer_list;
8979 while (m) {
8980 mb = m->next;
8981 free(m->id);
8982 free(m);
8983 m = mb;
8984 }
8985
8986 /* Destroy and unlink this curmailers section.
8987 * Note: curmailers is backed up into *last.
8988 */
8989 free(curmailers->id);
8990 curmailers = curmailers->next;
8991 free(*last);
8992 *last = curmailers;
8993 }
8994 }
8995
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008996 /* Update server_state_file_name to backend name if backend is supposed to use
8997 * a server-state file locally defined and none has been provided */
8998 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8999 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9000 curproxy->server_state_file_name == NULL)
9001 curproxy->server_state_file_name = strdup(curproxy->id);
9002 }
9003
Willy Tarreau34eb6712011-10-24 18:15:04 +02009004 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009005 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009006 MEM_F_SHARED);
9007
Willy Tarreaubb925012009-07-23 13:36:36 +02009008 if (cfgerr > 0)
9009 err_code |= ERR_ALERT | ERR_FATAL;
9010 out:
9011 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009012}
9013
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009014/*
9015 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9016 * parsing sessions.
9017 */
9018void cfg_register_keywords(struct cfg_kw_list *kwl)
9019{
9020 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9021}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009022
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009023/*
9024 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9025 */
9026void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9027{
9028 LIST_DEL(&kwl->list);
9029 LIST_INIT(&kwl->list);
9030}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009031
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009032/* this function register new section in the haproxy configuration file.
9033 * <section_name> is the name of this new section and <section_parser>
9034 * is the called parser. If two section declaration have the same name,
9035 * only the first declared is used.
9036 */
9037int cfg_register_section(char *section_name,
9038 int (*section_parser)(const char *, int, char **, int))
9039{
9040 struct cfg_section *cs;
9041
9042 cs = calloc(1, sizeof(*cs));
9043 if (!cs) {
9044 Alert("register section '%s': out of memory.\n", section_name);
9045 return 0;
9046 }
9047
9048 cs->section_name = section_name;
9049 cs->section_parser = section_parser;
9050
9051 LIST_ADDQ(&sections, &cs->list);
9052
9053 return 1;
9054}
9055
Willy Tarreaubaaee002006-06-26 02:48:02 +02009056/*
David Carlier845efb52015-09-25 11:49:18 +01009057 * free all config section entries
9058 */
9059void cfg_unregister_sections(void)
9060{
9061 struct cfg_section *cs, *ics;
9062
9063 list_for_each_entry_safe(cs, ics, &sections, list) {
9064 LIST_DEL(&cs->list);
9065 free(cs);
9066 }
9067}
9068
9069/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009070 * Local variables:
9071 * c-indent-level: 8
9072 * c-basic-offset: 8
9073 * End:
9074 */